0

在 flex 中编写令牌生成器时,我遇到了这个烦人的错误:“无法识别的规则”

我的代码是:

/* Keywords */

TYPE        int|double|bool|char
LOGICAL     if|else|for|foreach|do|while|switch|return
MACROWORD   import|define|ifndef|endif|elseif|udef
MACRO       "#"{MACROWORD}

KEYWORD     {TYPE}|{LOGICAL}|{MACRO}

/* Literals */

DIGIT       [0-9]
DIGITS      {DIGIT}+
OPT_FRAC    ("."{DIGITS})?
OPT_EXP     (E(+|-){DIGITS})?

NUMBER      {DIGITS}{OPT_FRAC}{OPT_EXP}

LETTER      [a-zA-Z]

/* Identifier */

ID          {LETTER}({LETTER}|{DIGIT})*

/* Operators */

OPERATOR    "+"|"-"|"*"|"/"|"^"|"=""="|"<""="|">""="|">"|"<"|"!""=""

%%

{KEYWORD}   printf("(Keyword, %s)\n", yytext);

{NUMBER}    printf("(Numeric Literal, %s)", yytext);

{ID}    printf("(Identifier, %s)", yytext);

{OPERATOR}  printf("(Operator, %s", yytext);

[ \n\t]     /* Ignore Whitespace */

"{"         printf("(L Bracket, %s)", yytext);

"}"         printf("(R Bracket, %s)", yytext);

"("         printf("(L Parens, %s)", yytext);

")"         printf("(R Parens, %s", yytext);

";"         printf("(Semicolon, %s", yytext);

%%

main()
{
    yylex();
}

可悲的是,这只会导致:

"Scanner.lex:39: unrecognized rule" 重复19 次后面跟着一个实例:

“Scanner.lex:43:无法识别的规则”

第 39 行是:

{NUMBER}    printf("(Numeric Literal, %s)", yytext);

第 43 行是:

{OPERATOR}  printf("(Operator, %s", yytext);

我在互联网上搜索并在 stackoverflow 上找到了这个答案,其中建议在定义行的开头添加“^”,所以我将第 39 行引用(NUMBER)更改为:

NUMBER    ^{DIGITS}{OPT_FRAC}{OPT_EXP}

什么都没做。有什么建议么?

4

2 回答 2

1

吓坏了,因为+OPT_EXP 中没有任何内容+。(这是一个 RE +,而不是文字加号。)

您的 OPERATOR 定义有一个太多的双引号。

于 2013-04-21T08:26:15.270 回答
0
OPT_EXP     ([Ee][-+]{DIGITS})?
OPERATOR1   [-+*/=^><]
OPERATOR2   ==|<=|>=|==|!=

如果我们只对运算符使用一个定义,就会有问题。原因是如果 flex 看到<=它会匹配什么?作为一个<然后一个=或作为一个<=整体?我不认为 lex 支持前瞻。出于这个原因,我决定OPERATOR分成两个定义OPERATOR1OPERATOR2. 然后在规则部分你有2条规则

{OPERATOR2}  printf("(Operator, %s", yytext);
{OPERATOR1}  printf("(Operator, %s", yytext);

我们知道 lex 会优先匹配最长的规则,所以在规则的情况下<={OPERATOR2}触发

  • 注意 1:当我将-其作为字符类中的第一个字符时,例如[-+*/],它被视为常规字符,而不是表示范围的特殊字符。[+-*/]例如,在 and 之间是错误的,表示and-之间的所有字符。+*+*
  • 注 2:我确定这^不是字符类^中的第一个字符,因为字符类中的第一个字符表示否定。[^0-9]例如,表示匹配除数字之外的所有字符。
于 2013-04-21T09:23:55.337 回答