Flex“无法识别的错误”

时间:2013-04-21 07:59:02

标签: c regex flex-lexer

在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:无法识别的规则”重复 19次,然后是一个实例:

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

第39行是:

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

和第43行是:

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

我在互联网上搜索并发现this answer also on stackoverflow其他建议在定义行的开头添加“^”,所以我将第39行引用(NUMBER)更改为:

NUMBER    ^{DIGITS}{OPT_FRAC}{OPT_EXP}

哪个绝对没有。 有什么建议吗?

2 个答案:

答案 0 :(得分:1)

因为OPT_EXP中的++没有任何关系,所以它很吓人。 (这是一个RE +,而不是字面加号。)

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

答案 1 :(得分:0)

OPT_EXP     ([Ee][-+]{DIGITS})?
OPERATOR1   [-+*/=^><]
OPERATOR2   ==|<=|>=|==|!=

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

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

我们知道lex会考虑最长的匹配规则,所以在<= {OPERATOR2}规则会触发

的情况下
  • 注1:当我将-作为字符类中的第一个字符时,例如[-+*/],它被视为常规字符,而不是特殊字符指示范围。例如,[+-*/]会出错,因为-+之间的*表示+*之间的所有字符。
  • 注意2:我确保^不是字符类中的第一个字符,因为^作为字符类中的第一个字符意味着否定。例如,[^0-9]表示匹配除数字之外的每个字符。