Compiler construction 查找Flex Yacc中发生语法错误的位置

Compiler construction 查找Flex Yacc中发生语法错误的位置,compiler-construction,bison,yacc,lex,Compiler Construction,Bison,Yacc,Lex,我对莱克斯和亚克还很陌生 我正在设计一个编译器,它可以生成三个地址代码 如何在代码中找到语法错误发生的位置 进入后: flex lexer.l bison -dy parser.y gcc lex.yy.c y.tab.c -o program.exe 我尝试以下输入: { int abc = 234 ; } 然后它给了我语法错误 我怎样才能修好它 这是我的雷克瑟 lexer.l: %{ #include "y.tab.h" #include <string.h> int yy

我对莱克斯和亚克还很陌生

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

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

进入后:

flex lexer.l
bison -dy parser.y
gcc lex.yy.c y.tab.c -o program.exe
我尝试以下输入:

{ int abc = 234 ; }
然后它给了我语法错误

我怎样才能修好它

这是我的雷克瑟

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);
}
%{
#包括“y.tab.h”
#包括
int yyerror(字符*错误消息);
%}
字母[a-zA-z]
数字[0-9]
id{letter}({letter}{digit})*
ws[\t]
%%
{ws};
\{{return 300;}
\}{返回301;}
\;          {返回分号;}
“if”{返回if;}
“int”{return int;}
“float”{返回float;}
“char”{return char;}
\={返回赋值;}
{id}{strcpy(yylval.str,yytext);返回id;}
{digit}+{yylval.ival=atoi(yytext);返回编号;}
.           {yyerror(“无效命令”);}
%%
内部主(空)
{
yyparse();
printf(“完成”);
返回0;
}
int-yywrap(无效)
{
返回0;
}
int yyerror(字符*错误消息)
{
fprintf(stderr,“嘿!%s\n”,errormsg);
出口(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
    ;
%{
#包括
#包括
#包括
int yylex(无效);
int yyerror(常量字符*s);
%}
%并集{int ival;双dval;字符str[120];}
%标记INT如果分号指定数字
%代币浮动
%令牌ID字符
%%
节目:
块
;
区块:
“{'Stmts'}”
;
STMT:
Stmts Stmt
|Stmt
;
Stmt:
块
|IfStmt
|转让STMT
|十二月
;
IfStmt:
如果“('Expr')”Stmt{printf(“如果找到”);}
;
转让STMT:
类型ID分配Expr分号{printf(“int found!”);}
;
十二月
类型ID分号
;
类型:
国际的
|浮动
|煤焦
;
表达式:
数
;

通过使用
-DYYDEBUG=1'
进行编译,您可以让bison输出它正在做的事情:

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
注意,语法分析器无法识别lexer返回的第一个标记

对于
{
,您将返回
300
,但解析器需要
{'
,因此只需修复lexer规则:

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

然后,您将得到一个完成的解析,尽管它挂起了


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

当您试图找出Bison的语法错误时,要做的第一件事是将
%define parse.error verbose
选项添加到Bison文件中。这将把错误消息更改为更详细的内容elpful不仅仅是“语法错误”。请注意,这是Bison特有的功能,因此在调用Bison时需要删除
-y
标志。执行此操作时,错误消息将更改为:

syntax error, unexpected $undefined, expecting '{'
所以它告诉你它得到了一个
$undefined
,而它期望得到一个
{
。那么
$undefined
是什么呢?这是Bison如何显示任何它不知道名称的令牌。如果令牌是ASCII中的整数,它将显示为
'x'
(这里不是
x
,而是给定的ASCII字符)。如果已使用
%token
定义了令牌,则它将显示为与该
%token
声明关联的名称。只有在两者都不存在的情况下,才会获得
$undefined

因此,您的lexer返回的内容既不是ASCII字符,也不是已定义的标记。因此,让我们看看您的lexer是否有类似的内容,并确信:

\{          { return 300; }
\}          { return 301; }
当你的lexer看到大括号时,它将分别返回300或301。它们既不是字符,也不是使用
%token
定义的标记,因此它们对Bison来说毫无意义

因为您的解析器希望看到
'{'
'}'
,所以上面应该分别说
返回'{';
返回'}';
(或者
返回yytext[0];
,如果您愿意的话,在这两种情况下都是如此)。或者您可以在解析器中定义
%LBRACE RBRACE
,使用它们代替
'{'
'}'
规则中,并在lexer中返回它们。无论哪种方式,都不应该在lexer中返回任意整数



您还需要在
yywrap
中返回1而不是0,或者使用
noyywrap
选项将其完全删除。返回0会使lexer在到达文件末尾后等待进一步输入。

语法错误是什么?请在帖子中写下语法错误是“语法错误”.这正是Bison使用默认选项时出现的语法错误。
\{          { return 300; }
\}          { return 301; }