- 作者:xiaoxiao
- 发表时间:2020-12-23 10:57
- 来源:未知
LET'S BUILD A COMPILER!(4)---第三部分:再论表达式续
空白字符
结束本章之前,我们再来讨论一下空白字符的问题。现在这个版本的分析器会在读到一个空白字符的地方停下来。这是相当不友好的行为。所以让我们消除这个最后的限制,使分析器的表现更有商业产品的味道。
处理空白字符的关键在于制定一条规则,规定分析器改如何处理对待输入的空白字符,并在整个分析器中都遵守它。目前为止,空白字符还是不被允许的,我们可以假定在每个分析动作之后,先行字符Look都包含的是个有意义的字符,然后可以立即验证这点。我们设计的方法就是基于上述原则。
具体来说,就是每个需要先行读取输入流的过程都必须忽略空白字符,并且最后Look变量中只能保留非空白字符。所幸,我们是用GetName,GetNum和Match完成大部分了输入操作,所以只有三个过程(再加上Init过程)需要修改。
首先,定义一个新的识别空白字符的过程。
{--------------------------------------------------------------}{ Recognize White Space }
function IsWhite(c: char): boolean;begin IsWhite := c in [' ', TAB];end;{--------------------------------------------------------------}
还需要一个过程“吃掉”空白字符,直到遇见一个非空白字符。
{--------------------------------------------------------------}{ Skip Over Leading White Space }
procedure SkipWhite;begin while IsWhite(Look) do GetChar;end;{--------------------------------------------------------------}
现在,在Match,GetName和GetNum过程中调用SkipWhite:
{--------------------------------------------------------------}{ Match a Specific Input Character }
procedure Match(x: char);begin if Look <> x then Expected('''' + x + '''') else begin GetChar; SkipWhite; end;end;
{--------------------------------------------------------------}{ Get an Identifier }
function GetName: string;var Token: string;begin Token := ''; if not IsAlpha(Look) then Expected('Name'); while IsAlNum(Look) do begin Token := Token + UpCase(Look); GetChar; end; GetName := Token; SkipWhite;end;
{--------------------------------------------------------------}{ Get a Number }
function GetNum: string;var Value: string;begin Value := ''; if not IsDigit(Look) then Expected('Integer'); while IsDigit(Look) do begin Value := Value + Look; GetChar; end; GetNum := Value; SkipWhite;end;{--------------------------------------------------------------}