Flex Yacc中出现语法错误的地方

问题描述 投票:0回答:2

我对lex和yacc很陌生。

我正在设计一个可以生成三个地址的代码的编译器。

如何找到我的代码中语法错误发生的位置?

输入后:

flex lexer.l
bison -dy parser.y
gcc lex.yy.c y.tab.c -o program.exe

我尝试输入:

{ int abc = 234 ; }

然后它给我语法错误!

我该如何解决?

这是我的Lexer

lexer.l:

%{

#include "y.tab.h"
#include <string.h>
int yyerror(char *errormsg);

%}

letter  [a-zA-z]
digit   [0-9]
id      {letter}({letter}|{digit})*
ws      [ \t]


%%
{ws}        ;
\{          { return 300; }
\}          { return 301; }
\;          { return SEMICOLON; }
"if"        { return IF; }
"int"       { return INT; }
"float"     { return FLOAT; }
"char"      { return CHAR; }
\=          { return ASSIGN; }      
{id}        {strcpy(yylval.str,yytext) ; return ID; }
{digit}+    {yylval.ival=atoi(yytext); return NUMBER; }
.           {yyerror("Invalid Command");}
%%



int main(void)
{
   yyparse();
   printf("DONE");
   return 0;
}

int yywrap(void)
{
   return 0;
}

int yyerror(char *errormsg)
{
    fprintf(stderr, "hey!%s\n", errormsg);
    exit(1);
}

这是我的解析器

parser.y:

%{

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int yylex(void);
int yyerror(const char *s);

%}


%union{int ival; double dval; char str[120]; }

%token INT ASSIGN NUMBER IF SEMICOLON
%token FLOAT
%token ID CHAR

%%

Program: 
        Block
        ;

Block:
        '{' Stmts '}'
        ;

Stmts:
        Stmts Stmt
        | Stmt
        ;

Stmt:
        Block
        |IfStmt
        |AssignStmt
        |DeclStmt
        ;


IfStmt:
        IF '(' Expr ')' Stmt  { printf("if found"); }
        ;


AssignStmt:     
        Type ID ASSIGN Expr SEMICOLON { printf("int found!"); }
        ;

DeclStmt:
        Type ID SEMICOLON
        ;


Type:
        INT
        |FLOAT
        |CHAR
        ;


Expr:
    NUMBER
    ;
compiler-construction bison yacc lex
2个回答
0
投票

您可以使用-DYYDEBUG=1'进行编译,以使野牛输出正在执行的操作:

gcc -DYYDEBUG=1 lex.yy.c y.tab.c -o program.exe

然后在将yydebug全局变量设置为真实值的情况下运行:

int main(void)
{

    #ifdef YYDEBUG
    yydebug = 1;
    #endif
   yyparse();
   printf("DONE");
   return 0;
}

为您的项目做这件事,收益

Starting parse
Entering state 0
Reading a token: Next token is token $undefined ()
hey!syntax error

IOW,语法分析器无法识别词法分析器返回的第一个标记。

您将300返回{,但是解析器期望'{',因此只需修复词法分析器规则:

//WRONG
\{          { return 300; }
\}          { return 301; }

to

//OK
 \{          { return '{'; }
 \}          { return '}'; }

然后您完成了解析,尽管挂起了。

挂起是由您在0中返回yywrap引起的。将其更改为1将删除它。


0
投票

尝试找出Bison的语法错误时,您要做的第一件事是将%define parse.error verbose选项添加到Bison文件中。这将使错误消息变得比“语法错误”更有用。请注意,这是Bison的特定功能,因此在调用Bison时需要删除-y标志。这样做,错误消息将更改为:

syntax error, unexpected $undefined, expecting '{'

所以它告诉您,当它期望$undefined时得到了{。那么$undefined是什么?这就是Bison如何显示其名称不知道的任何令牌的方式。如果令牌是ASCII中的整数,则将显示为'x'(此处将是给定的ASCII字符,而不是x)。如果令牌是使用%token定义的,它将显示为与%token声明关联的名称。只有在没有这种情况的情况下,您才会得到$undefined

因此您的词法分析器返回的内容既不是ASCII字符也不是已定义的标记。因此,让我们看看您的词法分析器是否有类似的东西,而且可以肯定:

\{          { return 300; }
\}          { return 301; }

[当您的词法分析器看到括号时,它将分别返回300或301。这些既不是字符也不是使用%token定义的标记,因此它们对Bison毫无意义。

由于您的解析器希望看到'{''}',因此上面的代码应分别表示return '{';return '}';(如果您愿意,在两种情况下也都说return yytext[0];)。或者,您可以在解析器中定义%token LBRACE RBRACE,而不是在'{'规则中使用'}'Block并在词法分析器中返回它们。无论哪种方式,您都绝对不应在词法分析器中返回任意整数。


您还想在yywrap中返回1而不是0,或者使用noyywrap选项将其完全删除。返回0使词法分析器在到达文件末尾后等待进一步的输入。

© www.soinside.com 2019 - 2024. All rights reserved.