在野牛中为非终端分配多种类型

时间:2014-04-06 08:04:18

标签: c++ parsing bison yacc

我正在尝试将多种数据类型分配给非终端号码并在谷歌上搜索我发现:Assigning multiple data types to a non-terminal in yacc。 但是这个语法对我来说似乎不起作用,因为运行它我得到以下错误:

new11.y:53.54-55: $3 of `initialization' has no declared type
new11.y:57.81-82: $5 of `increment' has no declared type
new11.y:70.33-34: $4 of `ifelse' has no declared type

这是我的代码:

  %union{
    int ival;
    float fval;
    char *sval;
}

// define the terminal symbol token types
%token <ival> INTEGER
%token <fval> FLOAT
%token <sval> BLOCK
%token <sval> GOTO
%token PRINT IF ELSE RETURN
%token LESSTHAN LESSTHANEQUALTO GREATERTHAN GREATERTHANEQUALTO EQUALTO
%token ADD SUB MUL DIV
%token <sval> IDENTIFIER 
%type <sval> comparison

%%
//grammar which bison will parse

start:
    block statements { ; }
    | start block statements { ; }
    ;

block:
    BLOCK { cout<<"Block : "<<$1<<endl; }
    ;

number:
    INTEGER { $<ival>$=$1 }
    | FLOAT { $<fval>$=$1 }
    ;

initialization:
    IDENTIFIER EQUALTO number { cout<<$1<<" = "<<$3<<endl; }
    ;

increment:
    IDENTIFIER EQUALTO IDENTIFIER ADD number { cout <<$1<<" = "<<$3<<" + "<<$5<<endl; }
    ;

goto:
    GOTO { cout<<"GOTO : "<<$1<<endl; }
    ;

printing:
    PRINT { cout<<"printf(...)"<<endl; }
    ;

ifelse:
    IF IDENTIFIER comparison number GOTO ELSE GOTO
    { cout <<"if "<<$2<<$3<<$4<<", "<<$5<<",else, "<<$7<<endl; }
    ;

comparison:
    LESSTHAN { $$="<"; }
    | LESSTHANEQUALTO { $$="<=" }
    | GREATERTHAN { $$=">" }
    | GREATERTHANEQUALTO { $$=">=" }
    ;

statement:
    initialization
    | printing
    | goto
    | increment
    | ifelse
    | RETURN
    ;

statements:
    statements statement 
    | statement
    ;

%%

main() {
    // open a file handle to a particular file:
    FILE *myfile = fopen("test.cfg", "r");
    // make sure it is valid:
    if (!myfile) {
        cout << "I can't open a.snazzle.file!" << 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));
}

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

我在哪里错了?我没有正确使用语法吗?

1 个答案:

答案 0 :(得分:1)

错误信息非常清楚。您的非终端initialization的{​​{1}} $3number需要number声明。 %type的{​​{1}}和$5的{​​{1}} increment也是$4,因此三次出现同样的问题。

您可能需要创建一个区分联合来表示整数或浮点数,并在ifelse中使用该联合:

number

然后:

%union

这个语法在Bison编译 - 在C ++级别可能有代码工作要做。如果匿名联合不在C ++中,请在struct Number { enum { INTEGER, FLOAT } type; union { float fval; int ival; }; }; 内添加联合名称。您的标记生成器需要同时设置%union { char *sval; Number nval; }; 的{​​{1}}和struct Numbertype字段。你不能在C ++中写简单的ival;您必须在其前面添加fval

struct Number