我对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
;
您可以使用-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
将删除它。
尝试找出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使词法分析器在到达文件末尾后等待进一步的输入。