1.如果我输入int a;
或float b;
语法正在使用LR解析来解析它。我已经阅读了LR如何工作的规则,但想知道它的逐步说明。
2.为什么我收到语法错误?我怎么知道它出现在哪条线上?
编辑问题2:%error-verbose给出了一个更详细的错误原因,我用带有id的flex文件替换了NAME令牌,它可以工作。
y.output
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;
}
答案 0 :(得分:0)
如果您想详细了解解析器的工作原理,最好使用野牛自己的trace facility。请注意,您必须做两件事:
-t
选项告诉bison生成跟踪代码; yydebug
设置为1以开始跟踪。还有其他有用的选项,都在Debugging Your Parser中描述。
如果添加
,Flex将自动跟踪输入行号%option yylineno
到你的flex prolog。完成后,您可以在yylineno
函数中使用全局变量yyerror
。请注意,由于在扫描程序中定义了yylineno
,因此必须在解析器中明确声明它:
void yyerror (const char *msg)
{
extern int yylineno;
fprintf(stderr, "At %d: %s\n", yylineno, msg);
}