如何定义(f)lex / bison模式(/ * comment * /)和/或(100 / * comment * /)

时间:2014-10-14 15:53:25

标签: yacc lex

如何定义lex模式()或(/ * rem /)和(/ foo / 100 / foo * /) 在使用gnu(f)lex工具。

_space [ \t]
id     [a-zA-Z_]+[a-zA-Z0-9_]
digit  [0-9]

math_ops   [\+\-\/\*\^\%]
rem_expr   (({_space}*)*|("/*".*"*/")*|("//".*)*|([\n]*))*
arr_digid  ("("*({digit}*|{id}*)*")"*){arr_expr1}*{math_ops}+
arr_expr1  {rem_expr}*{digit}*{rem_expr}*
arr_expr2  {rem_expr}*

%%

\({arr_expr2}*\)  {
    return _REM_;
}

\({arr_expr1}*\)  {
    return _PATTERN2_;
}

1 个答案:

答案 0 :(得分:1)

通常,您不会从词法分析器返回注释或空格。你为什么这样?根据定义,它们不是您尝试解析的程序语义的一部分。

总的来说,处理它们的最简单方法就是忽略它们。下面,第一个模式匹配除换行符之外的任何空格字符(使用[[:space:]]也忽略换行符),第二个模式是匹配C样式注释的方式。 ("/*".*"*/"不起作用,因为它会从一行的第一条评论的开头到最后一条评论的结尾匹配。)

[[:blank:]]  ;
[/][*][^*]*[*]+([^/*][^*]*[*]+)[/]  ;

模式没有动作(或者,通常在动作中没有return语句)这一事实意味着(f)lex生成的扫描程序将简单地继续分析下一个令牌。

其他一些说明:

  1. 没有必要为每个模式定义快捷方式。将模式直接放在lex动作中没有问题。而且您当然不需要为已经有快捷方式的字符类定义快捷方式(例如[[:blank:]][[:digit:]]

  2. 您不需要在字符类中反斜杠转义字符,尽管有几个字符顺序很重要。 (这就是我在C-comment模式中使用[*]的原因;我同样可以使用"*"\*,但我个人更喜欢[*]。)所以你可以定义:

    math_ops   [+/*^%-]
    

    - 必须位于列表的结尾或开头; ^ 不能在开头就行,而且(虽然你不能使用它)] 必须在开头。唯一需要反斜杠转义的字符就是反斜杠本身。

  3. 但是,我最好总是让单个字符标记在最后用一个默认规则处理:

    .    { return yytext[0]; }
    

    这更易于维护,并且无需为单字符标记创建任意标记名称。您可以在bison / yacc文件中使用单引号字符。