标记解析器的数字

时间:2010-06-11 12:06:35

标签: parsing tokenize

我正在编写我的第一个解析器,并且有一些问题会转义标记器。

基本上,我的tokenizer公开了一个nextToken()函数,它应该返回下一个标记。这些令牌以令牌类型区分。我认为拥有以下令牌类型是有意义的:

  • 符号(例如<:=(
  • WHITESPACE(标签,换行符,空格......)
  • 备注(/ * ... *之间的评论/或//通过新行之后的评论)
  • NUMBER
  • IDENT(例如函数或变量的名称)
  • STRING(“......”之间的东西)

现在,你觉得这有道理吗?

另外,我正在努力使用NUMBER令牌类型。您是否认为将其进一步拆分为NUMBERFLOAT令牌类型更有意义?如果我不是FLOAT令牌类型,我会收到NUMBER(例如402),SYMBOL(。)后跟另一个NUMBER(例如203)解析浮动。

最后,您认为令牌制作者在遇到-909时返回会更有意义吗?它应首先返回SYMBOL -,然后返回NUMBER 909还是立即返回NUMBER -909

5 个答案:

答案 0 :(得分:4)

最好通过使您的令牌类型与语法的终端符号紧密匹配来实现最佳效果。

在不知道语言/语法的情况下,我希望通过为“LESS_THAN”,“LESS_THAN_OR_EQUAL”以及“FLOAT”,“DOUBLE”,“INTEGER”等提供令牌类型来提供更好的服务。

答案 1 :(得分:4)

这取决于您的目标语言。

词法分析器背后的要点是返回令牌,以便为您的语言编写解析器。假设你的词法分析器在看到符合“[0-9] +”的符号时返回NUMBER。如果它看到非整数,例如“3.1415926”,它将返回NUMBER . NUMBER。虽然您可以在解析器中处理它,但如果您的词法分析器正在执行跳过空格和注释的适当工作(因为它们与您的解析器无关),那么您最终可能会错误地解析诸如“123 / * comment 之类的内容/。\ n / 其他评论* / 456“作为浮点数。

至于lexing“ - [0-9] +”再次作为NUMBER vs MINUS NUMBER,这取决于您的目标语言,但我通常会使用{{ 1}} MINUS,否则你最终会将“A = 1-2-3-4”作为NUMBER SYMBOL = NUMBER {{1 } NUMBER代替NUMBER NUMBER SYMBOL = NUMBER MINUS NUMBER MINUS { {1}}。

虽然我们正在讨论此主题,但我强烈推荐Language Implementation Patterns的作者Terrance Parr撰写的ANTLR一书。

答案 2 :(得分:3)

根据我对实际词法分析者的经验:

  1. 确保检查您是否确实需要评论/空格标记。编译器通常不需要它们,而IDE通常会这样做(例如,将注释颜色设置为绿色)。
  2. 通常没有单一的“操作员”令牌;相反,每个不同的运营商都有一个令牌。所以有一个PLUS令牌和AMPERSAND令牌以及LESSER_THAN令牌等。这意味着当令牌是标识符或某种文字时,你只关心词位(匹配的实际文本)。
  3. 避免拆分文字。如果"hello world"是字符串文字,则将其解析为单个标记。如果-3.058e18是浮点文字,也将其解析为单个标记。词典通常依赖于正则表达式,这些表达式足以表达所有这些内容,甚至更多。当然,如果文字足够复杂,你来分割它们(例如Smalltalk中的块文字)。

答案 3 :(得分:2)

我认为你问题的答案与NUMBER的语义紧密相关。 NUMBER应该是什么?一个总是正整数,一个浮点......

我建议你查找U ** x操作系统的flex和yacc(又名lex&amp; bison)工具:这些是强大的解析器和扫描器生成器,它们可以获取语法并输出可编译的随时可用的程序。

答案 4 :(得分:0)

这取决于你如何接受令牌,如果你逐字逐句地做,那么它可能有点棘手,但如果你是逐字逐句地进行,即

int a = a + 2.0
然后标记就是(丢弃空格)

int
a
=
a
+
2.0

因此,您不会遇到将.解释为令牌而是将整个字符串放入的情况 - 您可以在此处确定它是FLOAT还是NUMBER或您想要的任何内容。