Lexical Analyzer,具有表格驱动和字符分类功能

Lexical Analyzer with table-driven and character classification in rust

提问人:Matrix22 提问时间:9/10/2023 最后编辑:user2722968Matrix22 更新时间:9/10/2023 访问量:44

问:

我正在为 C 语言编写词法分析器作为 Rust 的练习,现在我成功地使用回溯实现了词法分析器,如下所示:

lex_keyword(input)
.or_else(|| lex_identifier(input))
.or_else(|| lex_integer(input))
...
.unwrap_or(lex_unexpected(input));

这按预期工作,但是它有点慢,因为它会尝试所有可能的解决方案,直到找到一个解决方案,并且每lex_function检查整个输入是否有效,然后尝试映射到令牌,例如在标识符上:

 let end = input.iter().position(|byte| byte.is_ascii_whitespace() || /* is a punctuator */).unwrap_or(input.len());

// And then

if input[..end].iter().all(|byte| /* is valid identifier member */) { /* Return an identifer */ } else { None }

我已经阅读了有关词法分析器生成器如何实现词法分析器的信息。

因此,他们基本上将语法转换为 NFA,然后转换为 DFA,并执行主循环(这在理论上是好的)。

我读过关于 lexflexyacc 的文章,并且看到它们不仅为 DFA 生成一个查找表,而是生成一堆查找表,并且还使用字符类。而且,如果你要实现一个 DFA,他们的查找表也不是那么大,其中一行(state)将有 128 列(ASCII 字符)。

我的问题是,如何实现字符类,以及如何在 DFA 的查找表中使用它们,或者我可以为不同的规则创建不同的查找表,例如:

token ::=
  keyword
| identifeer
| integer_literal
| float_literal
| ...

DFA_FOR_KEYWORD = [...]
DFA_FOR_IDENTIFIER = [...]
DFA_FOR_INTEGER = [...]
DFA_FOR_FLOAT = [...]
LEXER_DFA = [/* Which connects all the DFAs */]

还有关于character_classes,它们是如何编码的,你能为不同的部分重用同一个类吗?


例如:

假设标识符必须以字母“p”结尾

identifer ::= [a-zA-Z]*p

我会上多少节课?

  1. 一个用于 a-z,一个用于 A-Z,一个用于“p”
  2. 一个用于 a-zA-Z,一个用于“p”
  3. 一个用于 a-zA-Z,并检查它是否以“p”结尾

另一个问题是,如何在主循环中组装它们?

给定转换表,给定字符类和最后一个状态,您现在如何进行下一个转换(换句话说,如何编纂转换表以根据字符类移动)?

https://www.cs.man.ac.uk/%5C~pjj/cs211/ho/node6.html 查找此链接,但无法理解字符类的使用位置或它们的编码方式。

另外,如果您有关于此问题的一些资源,请随时分享

非常感谢您的建议

PS:我知道词法生成器可以完成所有这些事情,但是我想手动实现它作为练习的一部分。

Lexer DFA

评论

0赞 user2722968 9/10/2023
删除了 -tag,因为这个问题过于宽泛。rust

答: 暂无答案