<code class="language-text">token [NAME]: func
token [NAME]: fab
token [LPAR]: (
token [NAME]: number
token [RPAR]: )
token [COLON]: :
token [NEWLINE]:
token [INDENT]:
token [NAME]: if
token [LPAR]: (
token [NAME]: number
token [EQEQUAL]: ==
token [NUMBER]: 1
token [RPAR]: )
token [COLON]: :
token [NEWLINE]:
token [INDENT]:
token [NAME]: return
token [NUMBER]: 1
token [NEWLINE]:
token [DEDENT]:
token [NAME]: if
token [LPAR]: (
token [NAME]: number
token [EQEQUAL]: ==
token [NUMBER]: 2
token [RPAR]: )
token [COLON]: :
token [NEWLINE]:
token [INDENT]:
token [NAME]: return
token [NUMBER]: 2
token [NEWLINE]:
token [DEDENT]:
token [NAME]: return
token [NAME]: fab
token [LPAR]: (
token [NAME]: number
token [MINUS]: -
token [NUMBER]: 1
token [RPAR]: )
token [PLUS]: +
token [NAME]: fab
token [LPAR]: (
token [NAME]: number
token [MINUS]: -
token [NUMBER]: 2
token [RPAR]: )
token [NEWLINE]:
token [DEDENT]:
</code>
关键词: layout sensitive parsing, off-side rule<code class="language-text">funcdef: 'def' NAME parameters ':' funcdef_body {
$5.line > $1.line && $5.col > $1.col
}?
;
</code>
我有一个想法。
首先确定源代码的缩进是由空格控制还是制表符控制,并在之后使用一致的方式进行处理。为了便于说明,下面不妨假设我们需要处理的代码都是由制表符控制缩进的。
在词法解析的阶段,需要把制表符输出为一个token,比如叫tabToken。然后对于每个语句,就有这样一个特点:在换行符的后边的tabToken数目就是代码的层级数(特殊情况另说)。根据这个原理,处理的时候就可以在层级数变化的时候,插入花括号token:当层级数变大的时候,插入左花括号token;变小的时候,插入右花括号token。
那么,我们就可以使用处理C代码的方法来处理Python代码了。
我思考过这个问题: Cirru 解析缩进的方案
Leading whitespace (spaces and tabs) at the beginning of a logical line is used
to compute the indentation level of the line, which in turn is used to determine
the grouping of statements.
First, tabs are replaced (from left to right) by one to eight spaces such that
the total number of characters up to and including the replacement is a multiple
of eight (this is intended to be the same rule as used by Unix). The total
number of spaces preceding the first non-blank character then determines the
line’s indentation. Indentation cannot be split over multiple physical lines
using backslashes; the whitespace up to the first backslash determines the
indentation.
<code class="language-python"><span class="o">/*</span> <span class="n">Get</span> <span class="nb">next</span> <span class="n">token</span><span class="p">,</span> <span class="n">after</span> <span class="n">space</span> <span class="n">stripping</span> <span class="n">etc</span><span class="o">.</span> <span class="o">*/</span>
<span class="n">static</span> <span class="nb">int</span>
<span class="n">tok_get</span><span class="p">(</span><span class="n">register</span> <span class="n">struct</span> <span class="n">tok_state</span> <span class="o">*</span><span class="n">tok</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">p_start</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">p_end</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">register</span> <span class="nb">int</span> <span class="n">c</span><span class="p">;</span>
<span class="nb">int</span> <span class="n">blankline</span><span class="p">;</span>
<span class="o">*</span><span class="n">p_start</span> <span class="o">=</span> <span class="o">*</span><span class="n">p_end</span> <span class="o">=</span> <span class="n">NULL</span><span class="p">;</span>
<span class="n">nextline</span><span class="p">:</span>
<span class="n">tok</span><span class="o">-></span><span class="n">start</span> <span class="o">=</span> <span class="n">NULL</span><span class="p">;</span>
<span class="n">blankline</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="o">/*</span> <span class="n">Get</span> <span class="n">indentation</span> <span class="n">level</span> <span class="o">*/</span>
<span class="k">if</span> <span class="p">(</span><span class="n">tok</span><span class="o">-></span><span class="n">atbol</span><span class="p">)</span> <span class="p">{</span>
<span class="n">register</span> <span class="nb">int</span> <span class="n">col</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">register</span> <span class="nb">int</span> <span class="n">altcol</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">tok</span><span class="o">-></span><span class="n">atbol</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">tok_nextc</span><span class="p">(</span><span class="n">tok</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="s">' '</span><span class="p">)</span>
<span class="n">col</span><span class="o">++</span><span class="p">,</span> <span class="n">altcol</span><span class="o">++</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="s">'</span><span class="se">\t</span><span class="s">'</span><span class="p">)</span> <span class="p">{</span>
<span class="n">col</span> <span class="o">=</span> <span class="p">(</span><span class="n">col</span><span class="o">/</span><span class="n">tok</span><span class="o">-></span><span class="n">tabsize</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">tok</span><span class="o">-></span><span class="n">tabsize</span><span class="p">;</span>
<span class="n">altcol</span> <span class="o">=</span> <span class="p">(</span><span class="n">altcol</span><span class="o">/</span><span class="n">tok</span><span class="o">-></span><span class="n">alttabsize</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">*</span> <span class="n">tok</span><span class="o">-></span><span class="n">alttabsize</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="s">'</span><span class="se">\014</span><span class="s">'</span><span class="p">)</span> <span class="o">/*</span> <span class="n">Control</span><span class="o">-</span><span class="n">L</span> <span class="p">(</span><span class="n">formfeed</span><span class="p">)</span> <span class="o">*/</span>
<span class="n">col</span> <span class="o">=</span> <span class="n">altcol</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="o">/*</span> <span class="n">For</span> <span class="n">Emacs</span> <span class="n">users</span> <span class="o">*/</span>
<span class="k">else</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">tok_backup</span><span class="p">(</span><span class="n">tok</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="s">'#'</span> <span class="o">||</span> <span class="n">c</span> <span class="o">==</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span> <span class="p">{</span>
<span class="o">/*</span> <span class="n">Lines</span> <span class="k">with</span> <span class="n">only</span> <span class="n">whitespace</span> <span class="ow">and</span><span class="o">/</span><span class="ow">or</span> <span class="n">comments</span>
<span class="n">shouldn</span><span class="s">'t affect the indentation and are</span>
<span class="ow">not</span> <span class="n">passed</span> <span class="n">to</span> <span class="n">the</span> <span class="n">parser</span> <span class="k">as</span> <span class="n">NEWLINE</span> <span class="n">tokens</span><span class="p">,</span>
<span class="k">except</span> <span class="o">*</span><span class="n">totally</span><span class="o">*</span> <span class="n">empty</span> <span class="n">lines</span> <span class="ow">in</span> <span class="n">interactive</span>
<span class="n">mode</span><span class="p">,</span> <span class="n">which</span> <span class="n">signal</span> <span class="n">the</span> <span class="n">end</span> <span class="n">of</span> <span class="n">a</span> <span class="n">command</span> <span class="n">group</span><span class="o">.</span> <span class="o">*/</span>
<span class="k">if</span> <span class="p">(</span><span class="n">col</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">c</span> <span class="o">==</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span> <span class="o">&&</span> <span class="n">tok</span><span class="o">-></span><span class="n">prompt</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span>
<span class="n">blankline</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Let</span> <span class="n">it</span> <span class="n">through</span> <span class="o">*/</span>
<span class="k">else</span>
<span class="n">blankline</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Ignore</span> <span class="n">completely</span> <span class="o">*/</span>
<span class="o">/*</span> <span class="n">We</span> <span class="n">can</span><span class="s">'t jump back right here since we still</span>
<span class="n">may</span> <span class="n">need</span> <span class="n">to</span> <span class="n">skip</span> <span class="n">to</span> <span class="n">the</span> <span class="n">end</span> <span class="n">of</span> <span class="n">a</span> <span class="n">comment</span> <span class="o">*/</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="err">!</span><span class="n">blankline</span> <span class="o">&&</span> <span class="n">tok</span><span class="o">-></span><span class="n">level</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">col</span> <span class="o">==</span> <span class="n">tok</span><span class="o">-></span><span class="n">indstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="o">/*</span> <span class="n">No</span> <span class="n">change</span> <span class="o">*/</span>
<span class="k">if</span> <span class="p">(</span><span class="n">altcol</span> <span class="o">!=</span> <span class="n">tok</span><span class="o">-></span><span class="n">altindstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">indenterror</span><span class="p">(</span><span class="n">tok</span><span class="p">))</span>
<span class="k">return</span> <span class="n">ERRORTOKEN</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">col</span> <span class="o">></span> <span class="n">tok</span><span class="o">-></span><span class="n">indstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="o">/*</span> <span class="n">Indent</span> <span class="o">--</span> <span class="n">always</span> <span class="n">one</span> <span class="o">*/</span>
<span class="k">if</span> <span class="p">(</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="o">+</span><span class="mi">1</span> <span class="o">>=</span> <span class="n">MAXINDENT</span><span class="p">)</span> <span class="p">{</span>
<span class="n">tok</span><span class="o">-></span><span class="n">done</span> <span class="o">=</span> <span class="n">E_TOODEEP</span><span class="p">;</span>
<span class="n">tok</span><span class="o">-></span><span class="n">cur</span> <span class="o">=</span> <span class="n">tok</span><span class="o">-></span><span class="n">inp</span><span class="p">;</span>
<span class="k">return</span> <span class="n">ERRORTOKEN</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">altcol</span> <span class="o"> <span class="n">tok</span><span class="o">-></span><span class="n">altindstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">indenterror</span><span class="p">(</span><span class="n">tok</span><span class="p">))</span>
<span class="k">return</span> <span class="n">ERRORTOKEN</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">tok</span><span class="o">-></span><span class="n">pendin</span><span class="o">++</span><span class="p">;</span>
<span class="n">tok</span><span class="o">-></span><span class="n">indstack</span><span class="p">[</span><span class="o">++</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">]</span> <span class="o">=</span> <span class="n">col</span><span class="p">;</span>
<span class="n">tok</span><span class="o">-></span><span class="n">altindstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">]</span> <span class="o">=</span> <span class="n">altcol</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="o">/*</span> <span class="n">col</span> <span class="o"> <span class="n">tok</span><span class="o">-></span><span class="n">indstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">]</span> <span class="o">*/</span> <span class="p">{</span>
<span class="o">/*</span> <span class="n">Dedent</span> <span class="o">--</span> <span class="nb">any</span> <span class="n">number</span><span class="p">,</span> <span class="n">must</span> <span class="n">be</span> <span class="n">consistent</span> <span class="o">*/</span>
<span class="k">while</span> <span class="p">(</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span> <span class="o">></span> <span class="mi">0</span> <span class="o">&&</span>
<span class="n">col</span> <span class="o"> <span class="n">tok</span><span class="o">-></span><span class="n">indstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="n">tok</span><span class="o">-></span><span class="n">pendin</span><span class="o">--</span><span class="p">;</span>
<span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="o">--</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">col</span> <span class="o">!=</span> <span class="n">tok</span><span class="o">-></span><span class="n">indstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="n">tok</span><span class="o">-></span><span class="n">done</span> <span class="o">=</span> <span class="n">E_DEDENT</span><span class="p">;</span>
<span class="n">tok</span><span class="o">-></span><span class="n">cur</span> <span class="o">=</span> <span class="n">tok</span><span class="o">-></span><span class="n">inp</span><span class="p">;</span>
<span class="k">return</span> <span class="n">ERRORTOKEN</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">altcol</span> <span class="o">!=</span> <span class="n">tok</span><span class="o">-></span><span class="n">altindstack</span><span class="p">[</span><span class="n">tok</span><span class="o">-></span><span class="n">indent</span><span class="p">])</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">indenterror</span><span class="p">(</span><span class="n">tok</span><span class="p">))</span>
<span class="k">return</span> <span class="n">ERRORTOKEN</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">tok</span><span class="o">-></span><span class="n">start</span> <span class="o">=</span> <span class="n">tok</span><span class="o">-></span><span class="n">cur</span><span class="p">;</span>
<span class="o">/*</span> <span class="n">Return</span> <span class="n">pending</span> <span class="n">indents</span><span class="o">/</span><span class="n">dedents</span> <span class="o">*/</span>
<span class="k">if</span> <span class="p">(</span><span class="n">tok</span><span class="o">-></span><span class="n">pendin</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">tok</span><span class="o">-></span><span class="n">pendin</span> <span class="o"> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">tok</span><span class="o">-></span><span class="n">pendin</span><span class="o">++</span><span class="p">;</span>
<span class="k">return</span> <span class="n">DEDENT</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="n">tok</span><span class="o">-></span><span class="n">pendin</span><span class="o">--</span><span class="p">;</span>
<span class="k">return</span> <span class="n">INDENT</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">again</span><span class="p">:</span>
<span class="n">tok</span><span class="o">-></span><span class="n">start</span> <span class="o">=</span> <span class="n">NULL</span><span class="p">;</span>
<span class="o">/*</span> <span class="n">Skip</span> <span class="n">spaces</span> <span class="o">*/</span>
<span class="n">do</span> <span class="p">{</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">tok_nextc</span><span class="p">(</span><span class="n">tok</span><span class="p">);</span>
<span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="s">' '</span> <span class="o">||</span> <span class="n">c</span> <span class="o">==</span> <span class="s">'</span><span class="se">\t</span><span class="s">'</span> <span class="o">||</span> <span class="n">c</span> <span class="o">==</span> <span class="s">'</span><span class="se">\014</span><span class="s">'</span><span class="p">);</span>
<span class="o">/*</span> <span class="n">Set</span> <span class="n">start</span> <span class="n">of</span> <span class="n">current</span> <span class="n">token</span> <span class="o">*/</span>
<span class="n">tok</span><span class="o">-></span><span class="n">start</span> <span class="o">=</span> <span class="n">tok</span><span class="o">-></span><span class="n">cur</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="o">/*</span> <span class="n">Skip</span> <span class="n">comment</span><span class="p">,</span> <span class="k">while</span> <span class="n">looking</span> <span class="k">for</span> <span class="n">tab</span><span class="o">-</span><span class="n">setting</span> <span class="n">magic</span> <span class="o">*/</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="s">'#'</span><span class="p">)</span> <span class="p">{</span>
<span class="n">static</span> <span class="n">char</span> <span class="o">*</span><span class="n">tabforms</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"tab-width:"</span><span class="p">,</span> <span class="o">/*</span> <span class="n">Emacs</span> <span class="o">*/</span>
<span class="s">":tabstop="</span><span class="p">,</span> <span class="o">/*</span> <span class="n">vim</span><span class="p">,</span> <span class="n">full</span> <span class="n">form</span> <span class="o">*/</span>
<span class="s">":ts="</span><span class="p">,</span> <span class="o">/*</span> <span class="n">vim</span><span class="p">,</span> <span class="n">abbreviated</span> <span class="n">form</span> <span class="o">*/</span>
<span class="s">"set tabsize="</span><span class="p">,</span> <span class="o">/*</span> <span class="n">will</span> <span class="n">vi</span> <span class="n">never</span> <span class="n">die</span><span class="err">?</span> <span class="o">*/</span>
<span class="o">/*</span> <span class="n">more</span> <span class="n">templates</span> <span class="n">can</span> <span class="n">be</span> <span class="n">added</span> <span class="n">here</span> <span class="n">to</span> <span class="n">support</span> <span class="n">other</span> <span class="n">editors</span> <span class="o">*/</span>
<span class="p">};</span>
<span class="n">char</span> <span class="n">cbuf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span>
<span class="n">char</span> <span class="o">*</span><span class="n">tp</span><span class="p">,</span> <span class="o">**</span><span class="n">cp</span><span class="p">;</span>
<span class="n">tp</span> <span class="o">=</span> <span class="n">cbuf</span><span class="p">;</span>
<span class="n">do</span> <span class="p">{</span>
<span class="o">*</span><span class="n">tp</span><span class="o">++</span> <span class="o">=</span> <span class="n">c</span> <span class="o">=</span> <span class="n">tok_nextc</span><span class="p">(</span><span class="n">tok</span><span class="p">);</span>
<span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">c</span> <span class="o">!=</span> <span class="n">EOF</span> <span class="o">&&</span> <span class="n">c</span> <span class="o">!=</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span> <span class="o">&&</span>
<span class="p">(</span><span class="n">size_t</span><span class="p">)(</span><span class="n">tp</span> <span class="o">-</span> <span class="n">cbuf</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o"> <span class="n">sizeof</span><span class="p">(</span><span class="n">cbuf</span><span class="p">));</span>
<span class="o">*</span><span class="n">tp</span> <span class="o">=</span> <span class="s">'</span><span class="se">\0</span><span class="s">'</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">cp</span> <span class="o">=</span> <span class="n">tabforms</span><span class="p">;</span>
<span class="n">cp</span> <span class="o"> <span class="n">tabforms</span> <span class="o">+</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">tabforms</span><span class="p">)</span><span class="o">/</span><span class="n">sizeof</span><span class="p">(</span><span class="n">tabforms</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">cp</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">((</span><span class="n">tp</span> <span class="o">=</span> <span class="n">strstr</span><span class="p">(</span><span class="n">cbuf</span><span class="p">,</span> <span class="o">*</span><span class="n">cp</span><span class="p">)))</span> <span class="p">{</span>
<span class="nb">int</span> <span class="n">newsize</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">tp</span> <span class="o">+</span> <span class="n">strlen</span><span class="p">(</span><span class="o">*</span><span class="n">cp</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">newsize</span> <span class="o">>=</span> <span class="mi">1</span> <span class="o">&&</span> <span class="n">newsize</span> <span class="o"> <span class="mi">40</span><span class="p">)</span> <span class="p">{</span>
<span class="n">tok</span><span class="o">-></span><span class="n">tabsize</span> <span class="o">=</span> <span class="n">newsize</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">Py_VerboseFlag</span><span class="p">)</span>
<span class="n">PySys_WriteStderr</span><span class="p">(</span>
<span class="s">"Tab size set to </span><span class="si">%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="n">newsize</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">while</span> <span class="p">(</span><span class="n">c</span> <span class="o">!=</span> <span class="n">EOF</span> <span class="o">&&</span> <span class="n">c</span> <span class="o">!=</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">tok_nextc</span><span class="p">(</span><span class="n">tok</span><span class="p">);</span>
<span class="p">}</span>
</span></span></span></span></span></span></span></code>
个人感觉可以把tab和换行符当成token处理。\n\t* 这样,记录\t的数量,这样处理每一个statement都可以方便地知道在哪一层缩进了。