Lex yacc移位/减少错误

Lex yacc移位/减少错误,c,parsing,yacc,lex,operator-precedence,C,Parsing,Yacc,Lex,Operator Precedence,我正在学习lex和yacc编程以及这个yacc程序,以验证和评估算术表达式,从而减少冲突。在阅读了其他stackoverflow解释之后,我理解问题的重要性,但是,我不确定如何使用错误处理来解决问题。我想知道是否有人能帮我 我尝试过这样的关联处理程序: %token VARNAME %token DIGIT %token EQ %token ADD SUB MULT DIV %token LPAREN RPAREN %token END %left ADD SUB MULT DIV LPAREN

我正在学习lex和yacc编程以及这个yacc程序,以验证和评估算术表达式,从而减少冲突。在阅读了其他stackoverflow解释之后,我理解问题的重要性,但是,我不确定如何使用错误处理来解决问题。我想知道是否有人能帮我

我尝试过这样的关联处理程序:

%token VARNAME
%token DIGIT
%token EQ
%token ADD SUB MULT DIV
%token LPAREN RPAREN
%token END
%left ADD SUB MULT DIV LPAREN
%right RPAREN END
%nonassoc EQ VARNAME DIGIT
%token VARNAME
%token DIGIT
%token EQ
%token ADD SUB MULT DIV
%token LPAREN RPAREN
%token END
%left ADD SUB MULT DIV LPAREN
%right RPAREN END
%nonassoc EQ VARNAME DIGIT
但是,它不起作用,我很困惑。这是我的1.y文件:

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

int main (int argc, char* argv[])
{
    FILE *fp;
    extern FILE *yyin;
    extern int yylex();
    extern int yyparse();
    extern int yydebug;

    yydebug = 1;
    if (argc == 2)
    {
        fp = fopen(argv[1], "r");
        if (!fp)
        {
        fprintf (stderr, "Usage: %s <filename>\n", argv[0]);
        }
        else
        {
            yyin = fp;
            yyparse();
            fprintf (stdout, "***PARSE COMPLETE***\n");
        }
    }
    else 
        fprintf (stderr, "Usage: %s <filename>\n", argv[0]);
}

void yyerror (const char *err)
{
    fprintf (stderr, "Error: %s\n", err);
}

%}

%token VARNAME
%token DIGIT
%token EQ
%token ADD SUB MULT DIV
%token LPAREN RPAREN
%token END

%%
    statement:
    END
    |
    expression END  
    {printf ("DONE!\n");};
    |
    error 
    { printf(" INVALID EXPRESSION\n"); }
;

expression: 
    VARNAME 
    {printf("PARSED A VARIABLE!\n");};
    |
    DIGIT 
    {printf("PARSED A DIGIT!\n");};
    |
    expression ADD expression
    {printf("PARSED A PLUS SIGN!\n");};
    |
    expression SUB expression
    {printf("PARSED A MINUS SIGN!\n");};
    |
    expression MULT expression
    {printf("PARSED A MULTPLY SIGN!\n");};
    |
    expression DIV expression
    {printf("PARSED A DIVIDE SIGN!\n");};
    |
    expression EQ expression
    {printf("PARSED A EQUALS SIGN!\n");};
    |
    LPAREN expression RPAREN
    {printf("PARSED A PARENTHESIS!\n");};
    ;

%%

这种关联正确吗?

这些问题在本文中都有很好的阐述

正如@Jonathan Leffler所说:


您需要指定运算符的优先级和关联性。查找
%left
%right
%nonassoc
。或者用不同的方式写语法。例如,C标准中的语法不需要优先级或关联性


%token
项看起来似乎合理。我认为
%left
不需要
LPAREN
%right
也不需要RPAREN。我不确定您是否需要
%nonassoc
。我假设
“code”(
开头和
)“code”
结尾是试图格式化注释的人工制品。通常,您希望ADD和SUB的优先级低于MULT和DIV

在算术示例中,这些问题通常通过编写语法来解决:

expression : term
           | term ADD expression
           | term SUB expression
            ;

term : factor
     | factor MULT term
     | factor DIV term
     ;

factor : VARNAME
       | DIGIT
       | LPAREN expression RPAREN
       ;

现在,在明确的语法中定义了运算符的关联性和优先级。

需要指定运算符的优先级和关联性。查找
%left
%right
%nonassoc
。或者用不同的方式写语法。例如,C标准中的语法不需要优先级或关联性。@JonathanLeffler我在格式方面遇到了问题,但我尝试更新了文章。我是否正确地关联了数字、EQ和VARNAME?
%token
项看起来似乎合理。我认为
%left
不需要
LPAREN
%right
也不需要
RPAREN
。我不确定您是否需要
%nonassoc
。我假设
“code”(
开头和
)“code”
结尾是试图格式化注释的人工制品。通常,您希望ADD和SUB的优先级低于MULT和DIV。