compiler-construction - 查找 Flex Yacc 中发生语法错误的位置
问题描述
我对 lex 和 yacc 很陌生。
我正在设计一个可以制作三地址代码的编译器。
如何找到代码中发生语法错误的位置?
进入后:
flex lexer.l
bison -dy parser.y
gcc lex.yy.c y.tab.c -o program.exe
我试试这个输入:
{ int abc = 234 ; }
然后它给了我语法错误!
我该如何解决?
这是我的词法分析器
词法分析器.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);
}
这是我的解析器
解析器.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
for {
,但解析器期望'{'
,因此只需修复词法分析器规则:
//WRONG
\{ { return 300; }
\} { return 301; }
至
//OK
\{ { return '{'; }
\} { return '}'; }
然后你得到一个完成的解析,虽然一个挂起。
挂起是由您返回造成0
的yywrap
。将其更改为1
将删除它。
推荐阅读
- eclipse - 如何在 Eclipse 中定义一个快捷键来为我的项目生成所有 javadoc
- xamarin.forms - Xamarin.Forms - 使用来自 UWP 头项目的第 3 方 dll 库引用 UWP 类库项目类型
- c# - C# - 一个方法可以检查另一个方法对参数的使用吗?
- html - 只选择行,而不是从 html 中的表中选择标题
- java - PipedInput/PipedOutput Stream API 的同步替代方案?
- c++ - 确定 16 位二进制数是负数还是正数
- java - 是否始终使用 httpclient 在请求中发送 keep-alive 以及如何防止发送它
- arrays - 沿对角线设置对称矩阵
- go - 用于取消飞行中的例程的 golang 设计模式
- javascript - 如何将非本地 javascript 日期时区转换为 UTC?