不清楚如何将额外的制作添加到野牛语法来创建错误信息

时间:2016-05-31 20:34:17

标签: parsing bison yacc

这不是作业,但它来自一本书。

我收到了以下bison规范文件:

%{
#include <stdio.h>
#include <ctype.h>

int yylex();
int yyerror();
%}

%token NUMBER

%%

command : exp { printf("%d\n", $1); }
        ; /* allows printing of the result */

exp : exp '+' term { $$ = $1 + $3; }
    | exp '-' term { $$ = $1 - $3; }
    | term { $$ = $1; }
    ;

term : term '*' factor { $$ = $1 * $3; }
     | factor { $$ = $1; }
     ;

factor : NUMBER { $$ = $1; }
       | '(' exp ')' { $$ = $2; }
       ;

%%

int main() {
  return yyparse();
}

int yylex() {
  int c;

  /* eliminate blanks*/
  while((c = getchar()) == ' ');

  if (isdigit(c)) {
    ungetc(c, stdin);
    scanf("%d", &yylval);
    return (NUMBER);
  }

  /* makes the parse stop */
  if (c == '\n') return 0;

  return (c);
}

int yyerror(char * s) {
  fprintf(stderr, "%s\n", s);
  return 0;
} /* allows for printing of an error message */

任务是执行以下操作:

  

重写规范以添加以下有用的错误消息:   
“缺少右括号”,由字符串生成(2 + 3   
“缺少左括号”,由字符串 2 + 3)生成   
“缺少运算符”,由字符串 2 3 生成   
“缺少操作数”,由字符串(2 +)

生成

我能够提出的最简单的解决方案是执行以下操作:

half_exp : exp '+' { $$ = $1; }
         | exp '-' { $$ = $1; }
         | exp '*' { $$ = $1; }
         ;


factor : NUMBER { $$ = $1; }
       | '(' exp '\n' { yyerror("missing right parenthesis"); }
       |  exp ')' { yyerror("missing left parenthesis"); }
       | '(' exp '\n' { yyerror("missing left parenthesis"); }
       | '(' exp ')' { $$ = $2; }
       | '(' half_exp ')' { yyerror("missing operand"); exit(0); }
       ;

exp : exp '+' term { $$ = $1 + $3; }
    | exp '-' term { $$ = $1 - $3; }
    | term { $$ = $1; }
    | exp exp { yyerror("missing operator"); }
    ;

这些更改有效,但会导致很多冲突。

这是我的问题。

有没有办法以这种方式重写这个语法,以免产生冲突?

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

是的,有可能:

command : exp { printf("%d\n", $1); }
        ; /* allows printing of the result */

exp:  exp '+' exp   {
                // code
    }
    | exp '-' exp  {
                // code
    }
    | exp '*' exp  {
                // code
    }
    | exp '/' exp  { 
                // code
            }
    |'(' exp ')' {
             // code
    }

Bison允许不明确的语法。

我不知道如何重写语法以避免冲突。您只是错过了术语,因素等等。当您想要左递归上下文无关语法时,您可以使用这些。

从这个语法:

E -> E+T
    |T
T -> T*F
    |F
F -> (E)
    |num

一旦你从左递归中解放出来,你就会去:

E -> TE'    { num , ( }
E' -> +TE'  { + }
    | eps   { ) , EOI }
T -> FT'    { ( , num }
T' -> *FT'  { * }
    |eps    { + , ) , EOI }
F -> (E)    { ( }
    |num    { num }

这些集合与规则一起显示了使用该规则必须具有的输入字符。当然这只是简单算术表达式的例子,例如2 *(3 + 4)* 5 +(3 * 3 * 3 + 4 + 5 * 6)等。

如果您想了解有关此主题的更多信息,我建议您阅读&#34;左递归上下文无关语法&#34;。有一些很好的书籍涵盖了这个主题,还包括如何获取输入集。

但正如我上面所说,所有这一切都可以避免,因为 Bison允许模糊语法。