首页 > 解决方案 > 为什么在词法分析器规范中对换行符和空格的处理不同?

问题描述

我正在使用 F# 的 FsLex 来生成词法分析器。我很难从教科书中理解以下两行。为什么换行符 (\n) 的处理方式与空格不同?特别是,“lexbuf.EndPos <- lexbuf.EndPos.NextLine”与“Tokenize lexbuf”有何不同?

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

标签: f#lexerfslex

解决方案


Arule本质上是一个将词法分析器缓冲区作为参数的函数。规则左侧的每个大小写都输入中的给定字符(例如'\n')或字符类别 ( ) 匹配[' ' '\t' '\r']。花括号内的规则大小右侧的表达式{ ... }定义了一个动作。您粘贴的定义的目的似乎是tokenizer

该表达式Tokenize lexbuf是对Tokenize规则的递归调用。本质上,该规则忽略了空白字符。为什么?因为分词器旨在简化输入。空格在编程语言中通常没有意义,因此这条规则将其过滤掉。标记化输入通常会使以后编写解析器更简单。您最终会希望将其他情况添加到您的Tokenize规则中(例如,用于关键字、赋值语句和其他表达式)以生成完整的词法分析器定义。

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

由于您在这里只显示一个词法分析器片段,我只能猜测lexbug.EndPos它的用途,但为了诊断目的而保留这些信息是很常见的。


推荐阅读