在创建DFA后实现标识令牌的词法分析器

时间:2014-04-27 21:47:17

标签: compiler-construction lexer

我想了解有关实现词法分析器的一些内容,我不想使用扫描仪生成器。从我所读到的是,我用不同的令牌的正则表达式识别语言的规范。然后我应该做一个大的正则表达式ORing所有令牌的表达式,对吧?!然后创建NFA,然后创建这个正则表达式的DFA,对吧?!如果是这样,当一个单词与最终DFA匹配时,我怎么知道这个单词代表哪个标记?!

2 个答案:

答案 0 :(得分:3)

您在这里描述的是手动实现生成的扫描仪。那不是你怎么做的。只需编写一个包含大型switch语句的循环,其大小写是每个标记类型的首字母,每个case都是一个循环来使用其余的标记并返回其类型。除了没有返回之外,空白情况是相同的。标识符的大小写也需要查找关键字表。

答案 1 :(得分:2)

基于FSM的Lexer

手动编写有限状态机(FSM)词法分析器,循环输入中的字符并使用两级switch语句处理它:

  • 外部switch语句正在打开状态;
  • 内部switch语句正在打开已读取的字符。

这是处理令牌的有限状态机的实现。这样做的缺点是维护起来会很复杂,特别是如果有许多状态要处理每个令牌。好处是重构更容易利用有限状态机(例如使用转换表而不是switch语句)。

转换表类似于switch语句:行定义状态,列定义数据值,单元定义要转换到的下一个状态(用-1来表示停止处理)。使用此方法,可以使用结束状态来确定令牌类型。在这里,您将拥有一个token_type tokens[N_STATES];数组,然后您可以token = tokens[current_state]来获取令牌。

非FSM Lexer

另一种方法是打开第一个字符,然后读取该标记中的其余字符作为该case语句的一部分。这可以更容易阅读,更易于编写。

您还可以将字符拆分为不同的类(例如数字,字母,减号和小于),您可以将其定义为256项查找表。这可以简化案例陈述。

正则表达式

正如您所指出的那样,使用大正则表达式是有问题的,因为您无法获得令牌类型。这里的方法是获得与令牌匹配的正则表达式列表,并将其与令牌类型相关联。例如,在python中:

_tokens = [
    (re.compile('\\s+'), WhiteSpace),
    (re.compile('[a-zA-Z_][a-zA-Z0-9_]*'), Identifier),
    (re.compile('[0-9]+'), Integer),
]

您需要正确订购(例如,在标识符之前放置关键字匹配)。