在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}
哪个绝对没有。 有什么建议吗?
答案 0 :(得分:1)
因为OPT_EXP中的+
与+
没有任何关系,所以它很吓人。 (这是一个RE +
,而不是字面加号。)
您的OPERATOR定义中有太多双引号。
答案 1 :(得分:0)
OPT_EXP ([Ee][-+]{DIGITS})?
OPERATOR1 [-+*/=^><]
OPERATOR2 ==|<=|>=|==|!=
如果我们只使用一个运算符定义会有问题。原因是如果flex看到<=
它会匹配什么?作为<
,然后是=
或<=
所有togeather?我不认为lex支持前瞻。出于这个原因,我决定将OPERATOR
分为两个定义OPERATOR1
和OPERATOR2
。然后在规则部分中,您有 2条规则
{OPERATOR2} printf("(Operator, %s", yytext);
{OPERATOR1} printf("(Operator, %s", yytext);
我们知道lex会考虑最长的匹配规则,所以在<=
{OPERATOR2}
规则会触发
-
作为字符类中的第一个字符时,例如[-+*/]
,它被视为常规字符,而不是特殊字符指示范围。例如,[+-*/]
会出错,因为-
和+
之间的*
表示+
和*
之间的所有字符。^
不是字符类中的第一个字符,因为^
作为字符类中的第一个字符意味着否定。例如,[^0-9]
表示匹配除数字之外的每个字符。