syntax-error - 从 y.output 文件解析的解码步骤
问题描述
1.如果我输入int a;
或float b;
语法使用LR解析来解析它。我已经阅读了 LR 如何工作的规则,但想知道它的分步说明。
2.为什么会出现语法错误?我怎么知道它发生在哪条线上?
编辑问题 2:%error-verbose 给出了更详细的错误原因,我用 id 替换了 flex 文件中的 NAME 令牌,它可以工作。
y.输出
Terminals unused in grammar
LCURL
RCURL
LPAREN
RPAREN
NAME
DOUBLE
THEN
ELSE
"<"
">"
"<="
">="
"="
"!="
"+"
"-"
"*"
"/"
UMINUS
Grammar
0 $accept: start $end
1 start: program
2 program: program unit
3 | unit
4 unit: var_dec
5 var_dec: type_specifier declaration_list SEMICOLON
6 type_specifier: "int"
7 | FLOAT
8 | VOID
9 declaration_list: declaration_list COMMA ID
10 | declaration_list COMMA ID LTHIRD CONST_INT RTHIRD
11 | ID
12 | ID LTHIRD CONST_INT RTHIRD
Terminals, with rules where they appear
$end (0) 0
error (256)
"int" (258) 6
COMMA (259) 9 10
SEMICOLON (260) 5
ID (261) 9 10 11 12
FLOAT (262) 7
VOID (263) 8
LCURL (264)
RCURL (265)
LPAREN (266)
RPAREN (267)
CONST_INT (268) 10 12
LTHIRD (269) 10 12
RTHIRD (270) 10 12
NAME (271)
DOUBLE (272)
THEN (273)
ELSE (274)
"<" (275)
">" (276)
"<=" (277)
">=" (278)
"=" (279)
"!=" (280)
"+" (281)
"-" (282)
"*" (283)
"/" (284)
UMINUS (285)
Nonterminals, with rules where they appear
$accept (31)
on left: 0
start (32)
on left: 1, on right: 0
program (33)
on left: 2 3, on right: 1 2
unit (34)
on left: 4, on right: 2 3
var_dec (35)
on left: 5, on right: 4
type_specifier (36)
on left: 6 7 8, on right: 5
declaration_list (37)
on left: 9 10 11 12, on right: 5 9 10
State 0
0 $accept: . start $end
"int" shift, and go to state 1
FLOAT shift, and go to state 2
VOID shift, and go to state 3
start go to state 4
program go to state 5
unit go to state 6
var_dec go to state 7
type_specifier go to state 8
State 1
6 type_specifier: "int" .
$default reduce using rule 6 (type_specifier)
State 2
7 type_specifier: FLOAT .
$default reduce using rule 7 (type_specifier)
State 3
8 type_specifier: VOID .
$default reduce using rule 8 (type_specifier)
State 4
0 $accept: start . $end
$end shift, and go to state 9
State 5
1 start: program .
2 program: program . unit
"int" shift, and go to state 1
FLOAT shift, and go to state 2
VOID shift, and go to state 3
$default reduce using rule 1 (start)
unit go to state 10
var_dec go to state 7
type_specifier go to state 8
State 6
3 program: unit .
$default reduce using rule 3 (program)
State 7
4 unit: var_dec .
$default reduce using rule 4 (unit)
State 8
5 var_dec: type_specifier . declaration_list SEMICOLON
ID shift, and go to state 11
declaration_list go to state 12
State 9
0 $accept: start $end .
$default accept
State 10
2 program: program unit .
$default reduce using rule 2 (program)
State 11
11 declaration_list: ID .
12 | ID . LTHIRD CONST_INT RTHIRD
LTHIRD shift, and go to state 13
$default reduce using rule 11 (declaration_list)
State 12
5 var_dec: type_specifier declaration_list . SEMICOLON
9 declaration_list: declaration_list . COMMA ID
10 | declaration_list . COMMA ID LTHIRD CONST_INT RTHIRD
COMMA shift, and go to state 14
SEMICOLON shift, and go to state 15
State 13
12 declaration_list: ID LTHIRD . CONST_INT RTHIRD
CONST_INT shift, and go to state 16
State 14
9 declaration_list: declaration_list COMMA . ID
10 | declaration_list COMMA . ID LTHIRD CONST_INT RTHIRD
ID shift, and go to state 17
State 15
5 var_dec: type_specifier declaration_list SEMICOLON .
$default reduce using rule 5 (var_dec)
State 16
12 declaration_list: ID LTHIRD CONST_INT . RTHIRD
RTHIRD shift, and go to state 18
State 17
9 declaration_list: declaration_list COMMA ID .
10 | declaration_list COMMA ID . LTHIRD CONST_INT RTHIRD
LTHIRD shift, and go to state 19
$default reduce using rule 9 (declaration_list)
State 18
12 declaration_list: ID LTHIRD CONST_INT RTHIRD .
$default reduce using rule 12 (declaration_list)
State 19
10 declaration_list: declaration_list COMMA ID LTHIRD . CONST_INT RTHIRD
CONST_INT shift, and go to state 20
State 20
10 declaration_list: declaration_list COMMA ID LTHIRD CONST_INT . RTHIRD
RTHIRD shift, and go to state 21
State 21
10 declaration_list: declaration_list COMMA ID LTHIRD CONST_INT RTHIRD .
$default reduce using rule 10 (declaration_list)
我的输出是这个
type_specifier -> INT
syntax error
我正在添加 flex 和 bison 文件以防万一。Flex 文件:scanner.l
%option noyywrap
%{
#include<stdlib.h>
#include<stdio.h>
#include "y.tab.h"
#include "SymbolTable.h"
#include "SymbolInfo.h"
#include "ScopeTable.h"
void yyerror (char *);
extern YYSTYPE yylval;
extern SymbolTable *table;
int line_count = 1;
%}
NAME [a-z]*
DOUBLE (([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+))
id NAME
newline \n
%%
{newline} {line_count++;}
[ \t]+ {}
(([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+)) {
yylval.f = atof(yytext);
return DOUBLE;
}
"int" {return INT;}
"float" {return FLOAT;}
"void" {return VOID;}
[a-z]+ {
yylval.s = *yytext;
return NAME;
}
";" {return SEMICOLON;}
"," {return COMMA;}
"(" {return LPAREN;}
")" {return RPAREN;}
"{" {return LCURL;}
"}" {return RCURL;}
{id} {
SymbolInfo *s;
std::string str;
for(int i = 0;yytext[i] != '\0';i++)
{
str = yytext[i];
}
s = table -> scope_lookup(str);
if(s == NULL)
{
s->setName(str);
}
yylval.sym = s;
return ID;
}
%%
和 yacc 文件:parser.y
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "SymbolTable.h"
#include "SymbolInfo.h"
#include "ScopeTable.h"
int yyparse(void);
int yylex(void);
extern char* yytext;
extern FILE * yyin;
extern int tableSize;
FILE *logout;
extern int line_count;
SymbolTable *table;
void yyerror (char *s)
{
fprintf(stderr,"%s\n",s);
return;
}
%}
%union {
class SymbolInfo* sym;
char *s;
float f;
}
%verbose
%token INT "int"
%token COMMA SEMICOLON ID FLOAT VOID LCURL RCURL LPAREN RPAREN
%token CONST_INT LTHIRD RTHIRD
%token <s> NAME
%token <f> DOUBLE
%type <s> INT
//%expect 1
%precedence THEN
%precedence ELSE
%left "<" ">" "<=" ">=" "=" "!="
%left "+" "-"
%left "*" "/"
%left UMINUS
%%
start : program { printf("start -> program\n");
fprintf(logout,"%d : start -> program\n",line_count);
}
;
program : program unit {
printf("program -> program unit\n");
fprintf(logout,"%d : program -> program unit\n",line_count);
}
| unit {
printf("program -> unit\n");
fprintf(logout,"%d : program -> unit\n",line_count);
}
;
unit : var_dec {
printf("unit -> var_dec\n");
fprintf(logout,"%d : unit -> var_dec\n",line_count);
}
;
var_dec: type_specifier declaration_list SEMICOLON {
printf("var_dec -> type_specifier declaration_list SEMICOLON \n");
fprintf(logout,"%d -> var_dec: type_specifier declaration_list SEMICOLON \n", line_count);
}
;
type_specifier : INT {printf("type_specifier -> INT\n");
fprintf(logout,"%d : type_specifier-> INT\n", line_count);
}
| FLOAT {printf("type_specifier ->FLOAT\n");
fprintf(logout,"%d : type_specifier-> FLOAT\n",line_count);
}
| VOID {printf("type_specifier -> VOID\n");
fprintf(logout,"%d : type_specifier-> VOID\n",line_count);
}
;
declaration_list : declaration_list COMMA ID {
printf("declaration_list -> declaration_list COMMA ID\n");
fprintf(logout,"%d : declaration_list -> declaration_list COMMA ID\n",line_count);
}
| declaration_list COMMA ID LTHIRD CONST_INT RTHIRD {
printf("declaration_list -> declaration_list COMMA ID LTHIRD CONST_INT RTHIRD\n");
fprintf(logout,"%d : declaration_list -> declaration_list COMMA ID LTHIRD CONST_INT RTHIRD\n",line_count);
}
|ID {
printf("declaration_list -> ID\n");
fprintf(logout,"%d : declaration_list -> ID\n",line_count);
}
|ID LTHIRD CONST_INT RTHIRD {
printf("declaration_list -> ID LTHIRD CONST_INT RTHIRD\n");
fprintf(logout,"%d : declaration_list -> ID LTHIRD CONST_INT RTHIRD\n",line_count);
}
;
%%
int main(int argc, char *argv[])
{
FILE *fp ;
int token = 0;
if((fp = fopen(argv[1],"r")) == NULL)
{
fprintf(logout,"cannot open file");
exit(1);
}
logout = fopen("log.txt","w");
yyin = fp;
yyparse();
fclose(fp);
fclose(logout);
return 0;
}
解决方案
如果您想详细了解解析器的工作原理,最好使用 bison 自己的跟踪工具。请注意,您必须做两件事:
- 告诉 bison 生成跟踪代码,使用
-t
生成解析器时的选项; - 将全局变量设置
yydebug
为 1 以开始跟踪。
还有其他有用的选项,都在Debugging Your Parser中描述。
如果您添加,Flex 将自动跟踪输入的行号
%option yylineno
到你的 flex 序言。一旦你这样做了,你就可以yylineno
在你的yyerror
函数中使用全局变量。请注意,由于yylineno
在扫描仪中定义,您必须在解析器中显式声明它:
void yyerror (const char *msg)
{
extern int yylineno;
fprintf(stderr, "At %d: %s\n", yylineno, msg);
}
推荐阅读
- reporting-services - 将一个数据集返回的多个结果拟合到单个文本框中
- python-3.7 - def 关键字似乎总是给我一个错误反馈
- apache-camel - Camel PAHO 路由在连接回来时未收到离线消息
- java - 需要序列化的 EnqueueWork 导致 AsyncTask 崩溃
- opencv - 如何从 opencv.js 中找到角向量
- c++ - OpenAL 读取 WAV 文件库
- winforms - 在 PowerShell 中为新表单分离任务栏图标
- javascript - 如何从单独的组件传入道具?
- excel - 基于多列多IF条件的TEXTJOIN
- javascript - 如何修复下拉列表以使隐藏的 div 之一出现并附加