野牛减少问题

时间:2014-08-21 20:28:37

标签: bison

我一直在尝试在野牛工作中使用一个简单的计算器,但我得到了减少问题。

你能告诉我我做错了吗。

%{
#include <cstdio>
#include <iostream>
using namespace std;

// stuff from flex that bison needs to know about:
extern "C" int yylex();
extern "C" int yyparse();
extern "C" FILE *yyin;

void yyerror(const char *s);
%}

// Bison fundamentally works by asking flex to get the next token, which it
// returns as an object of type "yystype".  But tokens could be of any
// arbitrary data type!  So we deal with that in Bison by defining a C union
// holding each of the types of tokens that Flex could return, and have Bison
// use that union instead of "int" for the definition of "yystype":
%union {
    int ival;
    float fval;
    char *sval;
}

// define the "terminal symbol" token types I'm going to use (in CAPS
// by convention), and associate each with a field of the union:
%token <fval> NUM
%token <sval> STRING

/* Define the type of node our nonterminal symbols represent.
   The types refer to the %union declaration above. Ex: when
   we call an ident (defined by union type ident) we are really
   calling an (NIdentifier*). It makes the compiler happy.
 */
%type <fval> statement
%type <fval> statements

/* Operator precedence for mathematical operators */
%left TPLUS TMINUS
%left TMUL TDIV
%left UMINUS
%right TEXP

/* The Start*/
%start program

%%
// this is the actual grammar that bison will parse, but for right now it's just
// something silly to echo to the screen what bison gets from flex.  We'll
// make a real one shortly:

program: statements
    ;

statements: statement
    | statements statement
    ;

statement: NUM { $$ = $1; }
    |   statement TPLUS statement { $$ = $1 + $3; }
    | statement TMINUS statement { $$ = $1 - $3; }
    | statement TMUL statement { $$ = $1 * $3; }
    | statement TDIV statement { $$ = $1 / $3; }
    | TMINUS statement %prec UMINUS { $$ = -$2; }
    | statement TEXP statement { $$ = pow($1, $3); }
    | '(' statement ')' { $$ = $2; }
    ;

%%

int main() {
    // open a file handle to a particular file:
    FILE *myfile = fopen("Program.gb", "r");
    // make sure it is valid:
    if (!myfile) {
        cout << "I can't open Program.gb" << endl;
        return -1;
    }
    // set flex to read from it instead of defaulting to STDIN:
    yyin = myfile;

    // parse through the input until there is no more:
    do {
        yyparse();
    } while (!feof(yyin));

    return 0;
}

void yyerror(const char *s) {
    cout << "EEK, parse error!  Message: " << s << endl;
    // might as well halt now:
    exit(-1);
}

1 个答案:

答案 0 :(得分:2)

要将@ rici的评论转换为答案,问题只在于您所定义的语法含糊不清。解决这个问题的一种方法是引入行尾标记。为了使它有点C风格,你可以这样做:

statements: statement ';'
    | statements statement ';'
    ;

显然,如果词法分析器没有传回分号字符,则需要对词法分析器进行匹配更改。

您可能还会发现this question有助于解释转移 - 减少冲突是什么以及它们发生的原因。