Compiler construction 为函数原型和声明创建语法

Compiler construction 为函数原型和声明创建语法,compiler-construction,bison,Compiler Construction,Bison,我正在为一个学校项目制作一个编译器。一切正常,但我在定义函数语法时遇到了困难。我必须检测是否有零个或多个参数,以及函数是原型还是定义。我不断地变换/减少和/或减少/减少错误。我尝试过许多变体,但都没有用。这就是我所拥有的,只是在寻找另一个方向的指针或关于如何解决这个问题的想法 function : parameters ';' {free_ast($2); $$ = $1;} | parameters block {$$ = adopt1($1, $2)}

我正在为一个学校项目制作一个编译器。一切正常,但我在定义函数语法时遇到了困难。我必须检测是否有零个或多个参数,以及函数是原型还是定义。我不断地变换/减少和/或减少/减少错误。我尝试过许多变体,但都没有用。这就是我所拥有的,只是在寻找另一个方向的指针或关于如何解决这个问题的想法

function   : parameters ';'   {free_ast($2); $$ = $1;}
           | parameters block {$$ = adopt1($1, $2)}
           ;

parameters : paramlist ')'   {free_ast($2); $$ = $1;}
           | '(' identdecl ')' {free_ast($3); $$ = adopt_func2($1, $2);}
           ;

paramlist  : paramlist ',' identdecl {free_ast($2);
                                      $$ = adopt1($1, $2);}
           | '(' identdecl           {$$ = adopt_func2($1, $2);}

identdecl  : basetype TOK_ARRAY TOK_IDENT {$$ = adopt2($1, $2,
                                           change_symbol(
                                           $3, TOK_DECLID));}
           | basetype TOK_IDENT           {$$ = adopt1($1,
                                           change_symbol(
                                           $2, TOK_DECLID));}
           ;

block      : stateseq '}'       {free_ast($2); $$ = $1;}
           | ';'                {free_ast($1);}
           ;

采用函数2采用了一个定义,所以我的部分问题是在哪里采用函数。谢谢您的时间。

据我所知,这个问题与声明/定义的相似性无关。问题是,对于只有一个参数的参数列表,您有一个特殊情况,这会导致歧义:

parameters : paramlist ')'
           | '(' identdecl ')'
           ;

paramlist  : paramlist ',' identdecl 
           | '(' identdecl
           ;
因此
(类型id)
可以使用
参数
的第一个产品减少,其中
参数列表
可以使用其第二个产品减少,或者可以使用
参数
的第二个产品直接减少。我看不出对
参数的第二次生产有任何明显的需求,所以我建议删除它

然而,这是一种非常丑陋的语法书写方式,因为它隐藏了括号的对称性。它也不能识别参数为零的参数列表。所以我建议:

parameters : '(' paramlist ')'
           | '(' ')'

paramlist  : identdecl
           | paramlist ',' identdecl

我认为这更清楚。

原型和声明之间有什么区别?语法是什么?这与C++有什么关系?对不起,我添加了C++,我用C++编写了其他所有的东西。已经很晚了,我已经为此工作了一段时间。原型没有块语句和定义,就像C++一样。sointfoo()//proto和int foo(){…}用于定义。也有分号。C++中的原型是一个声明。定义是包含函数体的内容。我认为它来自其他部分,但当我现在解析文件时,我从解析器中得到一个语法错误,说意外的“(”,预期的“)”或“,”。这可能是我的其他语法,但没有移位/减少或减少/减少问题。尽管如此,函数和块中的分号还是有一个reduce/reduce问题。@corn_flakes:You允许
block
成为单个
,这意味着定义可能与声明完全相同。你真的应该纠正这种模糊性。我还建议您以与编写
参数
相同的方式重写
规则,以便
{
}
处于相同的生产中。(如图所示,没有任何产品包含
{
,因此这肯定不起作用。)是的,很抱歉。块的延续是stateseq:stateseq语句{$=adopt1($1,$2);}{$=change_符号($1,TOK_块);};