Lex&YACC编译错误:预期在'。'之前的')'。代币

时间:2019-01-12 13:11:08

标签: c bison flex-lexer yacc

我必须为一种迷你语言编写一个解析器,但遇到一些问题。这是YACC文件:

%{
#include <stdio.h>
int yylex();
void yyerror(char *s);

%}

%union {int num; char id; double d; char *s;}
%start program
%token <num> DIGIT
%token <s> IDENTIFIER
%token <num> NO
%type <num> term condition
%type <s> expression assignstmt stmt
%%
program : "##LAZY###" "vars" decllist cmpdstmt   {;}
        ;
decllist : declaration                           {;}
        | declaration decllist                  {;}
        ;
declaration : "in" IDENTIFIER                    {int $2;}
            | "in" '[' NO ']' IDENTIFIER         {int $5[$3];}
            ;                   
cmpdstmt : "exec" stmtlist "stop"                {;}
stmtlist : stmt                                  {;}
        | stmt stmtlist                         {;}
        ;
stmt : assignstmt                                {;}
    | ifstmt                                    {;}
    | whilestmt                                 {;} 
    ;
assignstmt : IDENTIFIER '=' expression           {$1 = $3;}
        ;
expression : expression '+' term                 {$$ = $1 + $3;}
        | term '+' term                       {$$ = $1 + $3;}
        ;
term : DIGIT                                     {$$ = $1;}
    | IDENTIFIER                                {$$ = $1;}
    ;
ifstmt : "if" '(' condition ')' '{' stmt '}'     {if($3){$6;}}
    ;
whilestmt : "wh" '(' condition ')' '{' stmt '}'  {while($3){$6;}}
        ;
condition : expression "<" expression            {$$ = ($1 < $3);}
        | expression "<=" expression           {$$ = ($1 <= $3);}
        | expression "==" expression           {$$ = ($1 == $3);}
        | expression "!=" expression           {$$ = ($1 != $3);}
        | expression ">=" expression           {$$ = ($1 >= $3);}
        | expression ">" expression            {$$ = ($1 > $3);}
        ;
%%

int main() {
    printf("WORKING\n");
    return yyparse();
}

void yyerror(char*s) { printf("%s\n", s); }

但是当我尝试使用以下代码进行编译时:cc lex.yy.c y.tab.c我收到以下错误,并且我不知道如何解决它们或为什么收到它们:

lazy.y: In function ‘yyparse’:
lazy.y:21:19: error: expected ‘)’ before ‘.’ token
declaration : "in" IDENTIFIER                    {int $2;}
                ^
lazy.y:22:19: error: expected ‘)’ before ‘.’ token
            | "in" '[' NO ']' IDENTIFIER         {int $5[$3];}

如果需要,我还将发布Lex文件。

2 个答案:

答案 0 :(得分:0)

来自

declaration : "in" IDENTIFIER                    {int $2;}
       | "in" '[' NO ']' IDENTIFIER         {int $5[$3];}
       ;                   

错误来自{int $2;}{int $5[$3];}

您对他们有什么期望?

那是合法的:

declaration : "in" IDENTIFIER                    {char * s = $2;}
            | "in" '[' NO ']' IDENTIFIER         {int i =  $5[$3];}
            ;

当然,这些变量是局部变量,因此没有真正的间断

答案 1 :(得分:0)

您已经知道YACC解析器生成器系列通过生成C代码进行工作,然后将其编译。可能不清楚的是,当涉及语义动作时,它们基本上充当模板引擎。如果您所提供的动作模板与之对应,那么他们非常愿意产生垃圾代码。除非您尝试编译结果代码,否则您可能不会发现他们已经这样做了。

此外,您的编译器和解析器生成器正在协同合作,向您显示YACC代码行,这些代码负责最终导致您所遇到的C语法错误。这对于确定位置您需要应用修复程序很有帮助,但是并不能很好地解释问题的性质。但是,这是尽力而为的,因为编译器只知道为什么C代码是错误的,而不是为什么派生它的YACC代码是错误的。

那么YACC代码为什么出错?有几个原因,但首先也是最主要的原因是,旨在通过设置特殊符号$$来设置产品语义的语义动作必须这样做。相反,以类型名称开头的C语句(例如由您的特定操作生成的)是声明。即使碰巧是一个有效值(在这里肯定不是这种情况),它也不会设置语义值。相反,您想要更类似的东西

{ $$ = $2; }

{ $$ = $5[$3]; }

但是您对数据类型有疑问。如果第一个操作中的$2和第二个操作中的$5与相同类型的令牌相对应,则上述两个操作都无法与您的{{ 1}}生产。作为一个大胆的猜测,也许您试图通过强制转换一个或两个以键入declaration,ala int来清理它。尽管这可以解决您的编译错误,但由于您需要了解原始类型,并且还因为从指针转换为$$ = (int) $2;可能会固有地有损,因此您将无法使用。 / p>

没有快速简便的修复方法。您需要重新考虑您的方法,更加注意数据类型以及如何保存和传达类型信息。

更新

在我看来,也许您根本没有尝试设置语义值,而是创建了一个生成C代码的解析器。如果真是这样,那么您就犯了帧错误。语义动作有助于生成的解析器本身的代码,即解析语言时使用的代码。如果您打算将自定义语言翻译成等效的C代码,则解析器需要将翻译的代码输出输出,而不是解析器的 part 。例如,您可以通过将所需的语句打印到文件中来实现这一点,但是更常见的方法是让解析器构建一个抽象的语法树,在解析完成后进行处理。