【发布时间】:2013-06-28 18:39:50
【问题描述】:
我正在编写一个用于解析计算机语言的语法,它可以与Parse::Eyapp 一起使用。这是一个 Perl 包,它简化了为常规语言编写解析器。它类似于 yacc 和其他 LALR 解析器生成器,但有一些有用的扩展,例如根据正则表达式定义标记。
我要解析的语言使用关键字来表示部分并描述控制流。它还支持用作数据占位符的标识符。标识符永远不能与关键字同名。
现在,棘手的部分来了:我需要将关键字与标识符分开,但它们可能看起来很相似,所以我需要一个不区分大小写地匹配标识符的正则表达式模式,仅此而已。
我想出的解决方案如下:
- 每个关键字都由以下形式的标记标识:
/((?i)keyword)(?!\w)/-
(?i)将为以下子模式应用不区分大小写的匹配 -
(?!\w)将不接受关键字后面的任何单词字符(a-z、0-9 等) - 这些字符将不属于匹配项
-
- 与另一个关键字开头相同的关键字列在较长关键字之后,因此它们首先匹配
- 用于匹配标识符的标记位于最后,因此仅在没有识别关键字时才会匹配
到目前为止,我提出的标记定义和部分语法运行良好,但仍有很多工作要做。不过,这不是我的问题。
我想问的是,我是不是走在正确的轨道上;是否有更好、更简单的正则表达式来匹配这些关键字?我应该停止并完全使用不同的方法进行语言解析吗?
顺便说一句,使用标记器匹配整个字符串而不是单个字符的想法来自 Parse::Eyapp 文档。我首先从逐个字符的语法开始,但这种方法不是很优雅,而且似乎与解析器生成器的灵活性相矛盾。写起来也很麻烦。
【问题讨论】:
-
这似乎属于codereview.se
-
可能,但我不是在这里要求进行代码审查。我宁愿对为编程语言开发一个好的分词器和(也许)语法有一些提示。我想我应该更清楚一点。
-
看来您走在了正确的轨道上。当我使用 lex/flex 时,我为我的关键字提出了类似的模式。最主要的是确保在关键字周围标记“单词边界”(您正在这样做),并在通用标识符之前匹配所有关键字标记。
-
不确定,但也许您可以使用
\b代替(?!\w)。 -
感谢@HamZa 的提示。我想这也可以(而且会更优雅)。