首页 > 解决方案 > 如何正确使用 %empty?

问题描述

我是 bison/fex 的新手,我正在尝试识别 1-3 个输入单词的模式。

我的 .l 将 WORD 识别为任何一系列小写字符,将 % 和 $ 字符视为它们自己的 ascii 值的标记,忽略空格,并将其他所有内容识别为 ERR 标记。

MISC    [\%\$]

%%

[a-z]+ { yylval.WORD = yytext; return WORD; }

[ \t\r\n]+  {} //ignore whitespace

{MISC}  return (int) yytext[0];

. return ERR; //unrecognized input

我的 .y 尝试识别由字符 % 和 $ 分隔的 1-3 个单词的序列。我想要这样即使我只输入 1 个单词,我仍然会得到一个完整的语句。当接收到无法识别的字符作为输入时,我不包含任何 ERR 令牌规则以在解析器中调用语法错误。

%{
    #include <stdio.h>
    int yylex();
    void yyerror(char* s){ 
        fprintf(stderr, "%s\n", s);
    };
%}

%define api.value.type union 

%token <char*> WORD
%nterm <char*> word1 word2 word3
%token ERR

%%

statement: word1 word2 word3 { printf("%s, %s, %s\n", $1, $2, $3); return 0; }
         ;

word1: WORD { $$ = $1; }
      ;

word2: %empty { $$ = "nothing"; }
      | '%' WORD { $$ = $2; }
      ;

word3: %empty { $$ = "nothing";}
      | '$' WORD { $$ = $2; }
      ;

%%

我的 main.c 在 yyparse() 上循环。理想情况下,我尝试每次迭代仅解析 1 行输入。

#include <unistd.h>
#include <stdio.h>

int yyparse();
int yylex();
extern FILE* yyin;
extern void yyrestart();

int main() {
    while(1) {
        printf("input: ");
        if (yyparse() == 0) {
            printf("success\n");
        };
        yyrestart(yyin);
    }
   return 0;
}

但是,我得到了不利的输出,我无法解释是什么原因造成的:

此外,如果我只输入 1 个 WORD,我的命令行会挂起,直到它收到额外的输入。这个额外的输入可以是任何东西。即使是通常被识别为 ERR 令牌并调用语法错误的字符也能以某种方式得到解决。

我希望我的解析器能够运行,即使我只给它 1 个字的输入。我认为通过包含子规则 word2 和 word3 的 %empty 我会得到这种行为,但我不确定我做错了什么。

标签: parsingcompiler-constructionbison

解决方案


推荐阅读