为什么在lexer规范中换行符和空白区被区别对待



我正在使用F#的FsLex来生成lexer。我很难理解课本上的以下两句话。为什么换行符(\n(与空白处不同?特别地;lexbuf。EndPos<-lexbuf。EndPos.NextLine";与";标记lexbuf"?

rule Tokenize = parse
| [' ' 't' 'r'] { Tokenize lexbuf }
| 'n'            { lexbuf.EndPos <- lexbuf.EndPos.NextLine; Tokenize lexbuf }

rule本质上是一个以lexer缓冲区为参数的函数。规则左侧的每个大小写都与输入中的给定字符(例如'n'(或字符类([' ' 't' 'r'](匹配。大括号{ ... }内规则大小合适的表达式定义了操作。粘贴的定义的目的似乎是标记化器

表达式Tokenize lexbuf是对Tokenize规则的递归调用。本质上,这个规则忽略了空白字符。为什么?因为标记化器的目的是简化输入。空白在编程语言中通常没有意义,所以这个规则会过滤掉它。标记化的输入通常会使以后编写解析器变得更简单。您最终会希望在Tokenize规则中添加其他事例(例如,关键字、赋值语句和其他表达式(,以生成完整的lexer定义。

第二条规则,即与n匹配的规则,也会忽略空白,但正如您正确指出的那样,它会做一些不同的事情。它所做的是在再次递归调用Tokenize之前,用下一行的末尾(lexbuf.EndPos.NextLine(的位置更新行末尾的位置(lexbuf.EndPos(。为什么?大概是为了在下一次递归调用中结束位置是正确的。

由于这里只显示了一个lexer片段,我只能猜测lexbug.EndPos的用途,但出于诊断目的保留这些信息是很常见的。

最新更新