我当前的lex文件如下所示:
%{
#include "foo.h"
void rem_as(char* string);
%}
DIGIT [0-9]
LITTERAL [a-zA-Z]
SEP [_-]|["."]|["\\"][ ]
FILE_NAME ({DIGIT}|{LITTERAL}|{SEP})*
PATH ({FILE_NAME}"/"{FILE_NAME})*|({FILE_NAME})
%%
"move" {return MOVE;}
"mv" {return MOVE;}
">" {return R_STDOUT;}
"2>" {return R_STDERR;}
"<" {return R_STDIN;}
"|" {return PIPE;}
"&" {return AND;}
"=" {return EQUAL_SIGN;}
"-"?{DIGIT}+ {yylval.integer = atoi(yytext); return NUM;}
{PATH} {rem_as(yytext); sscanf(yytext,"%[^\n]",yylval.string); return FILENAME;}
\n {return LINEBREAK;}
. ;
%%
这很有效。
例如,感谢这个语法
Move: MOVE FILENAME FILENAME { move($2, $3); }
;
我可以做像move a b
这样的事情。
现在我的问题:
将此添加到我的lex文件
VAR_NAME [a-zA-Z][a-zA-Z0-9_-]*
...
{VAR_NAME} {return VAR_NAME;} // declared before the "=" rule
我以前的规则中断,特别是FILENAME,现在必须包含'/'。
例如,使用这个语法:
VarDecl: VAR_NAME EQUAL_SIGN FILENAME { puts("foo"); }
;
a=b/
在a=b
引发语法错误时有效。
关于问题原因的任何想法?
感谢。
答案 0 :(得分:2)
您声明lex规则的顺序很重要,b匹配VAR_NAME,因此在尝试匹配PATH之前会发出VAR_NAME令牌,因此您最终会得到一个无效的VAR_NAME EQUAL_SIGN VAR_NAME规则。
简单的解决方案是让PATH成为你语法的一个规则,而不是你的词汇。
路径:VAR_NAME | FILE_NAME | VAR_NAME SLASH PATH | FILE_NAME SLASH PATH
在你的lex文件中添加/作为一个标记。