0

我当前的 le​​x 文件如下所示:

%{
#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

我以前的规则被打破了,尤其是文件名,现在必须包含一个'/'。

例如,使用以下语法:

VarDecl: VAR_NAME EQUAL_SIGN FILENAME { puts("foo"); }
       ;

a=b/a=b抛出语法错误时工作。

关于问题原因的任何想法?
谢谢。

4

1 回答 1

2

您声明 lex 规则的顺序很重要,b 匹配 VAR_NAME,因此在尝试匹配 PATH 之前发出 VAR_NAME 令牌,因此您最终得到一个无效的 VAR_NAME EQUAL_SIGN VAR_NAME 规则。

简单的解决方案是使 PATH 成为语法规则,而不是词汇规则。

路径:VAR_NAME | 文件名 | VAR_NAME 斜线路径 | FILE_NAME 斜线路径

在您的 lex 文件中添加 / 作为标记。

于 2013-05-02T12:05:01.110 回答