[英]Error in my yacc file
我正在尝试为某些语言创建解析器
每当我输入一个示例时,它都会输出“ Unsuccessful Parse”,并且我似乎找不到错误的地方。
这是我的.l文件和.y文件
%{
#include <stdio.h>
#include "stdlib.h"
#include"y.tab.h"
FILE *fp,*yyin;
extern void yyerror(char *);
extern int line = 1;
int pos = 1;
int com= 0;
int errorcomment;
%}
/* Regular definitions */
letter [a-zA-Z]
digit [0-9]
blank_str ([\t]|" ")
identifier {letter}({letter}|{digit})*([".""#""$""_"]?({letter}|{digit})+)?
num ([0-9]+)|(([0-9])+"."[0-9]*)([eE]["+""-"]?[0-9]+)?
wrongIdentifier [a-zA-z][a-zA-Z0-9]*["#""$""_""@""^""!""%"]
wrongNumber ([0-9]+)({letter}|["#""$""_""@""^""!""%""+""-" "|"])+
/* Regular definitions */
%option noyywrap
%%
\n {line++; pos = 1;}
{blank_str} {pos +=yyleng;}
[Ii][Ff] {pos +=yyleng; if(com==0)return IF;}
[Ee][Ll][Ss][Ee] {pos +=yyleng; if(com==0)return ELSE;}
[Rr][Ee][Tt][Uu][Rr][Nn] {pos +=yyleng; if(com==0)return RETURN;}
[Ww][Hh][Ii][Ll][Ee] {pos +=yyleng; if(com==0)return WHILE;}
[Vv][Oo][Ii][Dd] {pos +=yyleng; if(com==0)return VOID;}
[Ii][Nn][Tt] {pos +=yyleng; if(com==0)return INT;}
[Ll][Ee][Tt] {pos +=yyleng; if(com==0)return LET;}
{identifier} {pos +=yyleng; if(com==0)return ID;}
{num} {pos +=yyleng; if(com==0)return NUM;}
{wrongIdentifier} {pos +=yyleng; if(com==0)printf("\n**ERROR: Wrong Identifier in Line %d at %d\n\n\n", line, pos-yyleng);}
{wrongNumber} {pos +=yyleng;; if(com==0)printf("\n**ERROR: Wrong Number in Line %d at %d\n\n\n", line, pos-yyleng);}
"+" {pos +=yyleng; if(com==0)return ADDOP;}
"-" {pos +=yyleng; if(com==0)return ADDOP;}
"*" {pos +=yyleng; if(com==0)return MULOP;}
"/" {pos +=yyleng; if(com==0)return MULOP;}
"=" {pos +=yyleng; if(com==0)return AssgOP;}
"<" {pos +=yyleng; if(com==0)return RELOP;}
"<=" {pos +=yyleng; if(com==0)return RELOP;}
">" {pos +=yyleng; if(com==0)return RELOP;}
">=" {pos +=yyleng; if(com==0)return RELOP;}
"==" {pos +=yyleng; if(com==0)return RELOP;}
"!=" {pos +=yyleng; if(com==0)return RELOP;}
"," {pos +=yyleng; if(com==0)return COMMA;}
";" {pos +=yyleng; if(com==0)return Semicolon;}
"(" {pos +=yyleng; if(com==0)return Left_Brace;}
")" {pos +=yyleng; if(com==0)return Right_Brace;}
"[" {pos +=yyleng; if(com==0)return LSquare_Bracket;}
"]" {pos +=yyleng; if(com==0)return RSquare_Bracket;}
"{" {pos +=yyleng; if(com==0)return LWavy_Bracket;}
"}" {pos +=yyleng; if(com==0)return RWavy_Bracket;}
"/*" {pos +=yyleng; errorcomment = line; com=1;}
"*/" {pos +=yyleng; com=0;}
. {pos +=yyleng; printf("\n**ERROR : NOT IN THE ALPHABET in Line %d at %d\n\n\n", line, pos-yyleng);}
%%
这是.y文件
%{
#include <stdio.h> /* C declarations used in actions */
#include <stdlib.h>
#include <ctype.h>
extern int line;
extern FILE *yyin;
extern int yylex(void);
int yywrap()
{
return 1;
}
main()
{
yyparse();
if (yyparse()==0)
printf("Successful Parse.\n");
else
printf("Unsuccessful Parse.\n");
//return 0;
}
extern int yyerror (char * s) // allows for printing of an error msg
{
fprintf(stderr, "Error at line %d : %s\n",line, s);
return 0;
}
%}
%token ID
%token NUM
%token LET
%token IF
%token ELSE
%token INT
%token RETURN
%token VOID
%token WHILE
%token ADDOP
%token MULOP
%token RELOP
%token AssgOP
%token Semicolon
%token COMMA
%token Left_Brace
%token Right_Brace
%token LSquare_Bracket
%token RSquare_Bracket
%token LWavy_Bracket
%token RWavy_Bracket
%nonassoc LOWER_THAN_ELSE
%nonassoc ELSE
%%
program: declaration_list ;
declaration_list: declaration_list declaration
| declaration
;
declaration: var_declaration
| fun_declaration
;
var_declaration: type_specifier ID Semicolon
| type_specifier ID LSquare_Bracket NUM RSquare_Bracket Semicolon
;
type_specifier: INT
| VOID
;
fun_declaration: type_specifier ID Left_Brace params Right_Brace compound_stmt ;
params: param_list
| VOID
;
param_list: param_list COMMA param
| param
;
param: type_specifier ID
| type_specifier ID LSquare_Bracket RSquare_Bracket
;
compound_stmt: LWavy_Bracket local_declararions statement_list RWavy_Bracket ;
local_declararions: local_declararions var_declaration
|
;
statement_list: statement_list statement
|
;
statement: expression_stmt
| compound_stmt
| selection_stmt
| iteration_stmt
| return_stmt
;
expression_stmt: expression Semicolon
| Semicolon
;
selection_stmt: IF Left_Brace expression_stmt Right_Brace statement %prec LOWER_THAN_ELSE
| IF Left_Brace expression_stmt Right_Brace statement ELSE statement
;
iteration_stmt: WHILE Left_Brace expression_stmt Right_Brace statement ;
return_stmt: RETURN Semicolon
| RETURN expression Semicolon
;
expression: LET var AssgOP expression
| simple_expression
;
var: ID
| ID LSquare_Bracket expression RSquare_Bracket
;
simple_expression: additive_expression RELOP additive_expression
| additive_expression
;
additive_expression: additive_expression ADDOP term
| term
;
term: term MULOP factor
| factor
;
factor: Left_Brace expression Right_Brace
| var
| call
| NUM
;
call: ID Left_Brace args Right_Brace ;
args: arg_list
|
;
arg_list: arg_list COMMA expression
| expression
;
任何帮助都可以赞赏
我输入了一个简单的代码,例如int x [10]; 而且仍然不起作用
这个问题几个月来一直没有得到回答,因为它的构造不当,使任何人都难以解决。 您应该阅读https://stackoverflow.com/help/how-to-ask ,以提出有效的问题。 特别是没有尝试简化问题。 从本质上简化问题是调试的本质,因此是编程的秘密。 当我揭示此修复程序时,如何简化它将变得很清楚。 所有的评论都只是can。 与故障或其解决方案无关,而是简化故障的伪像。
我已经按编写的方式构建了代码,并对其进行了调试。 首先要注意的是仍然存在编译错误。 您至少应该消除编译器为您发现的错误,然后再寻求SO并寻求更多帮助。
在lex
文件(第6行)中,您具有以下内容:
extern void yyerror(char *);
在yacc
文件(第28行)中,您具有以下内容:
extern int yyerror (char * s) // allows for printing of an error msg
编译器会告诉您,这是不匹配的类型!
现在,它会根据您描述的错误进行构建和运行。
解决方案的下一阶段需要使用yacc内置的调试功能。 如果阅读yacc手册页,您会注意到它具有-t
选项,该选项将:
-t Change the preprocessor directives generated by yacc so that
debugging statements will be incorporated in the compiled code.
下一步是使用yydebug标志(第17行的yacc文件)启用这些调试语句:
main()
{ extern int yydebug; yydebug = 1 ; /* Enable debugging */
yyparse();
if (yyparse()==0)
现在,当您在示例( int x[10];
)上运行代码时,将得到以下输出:
Reading a token: Now at end of input.
Reducing stack by rule 1 (line 67):
$1 = nterm declaration_list ()
-> $$ = nterm program ()
Stack now 0
Entering state 3
Now at end of input.
Shifting token $end ()
Entering state 9
Stack now 0 3 9
Cleanup: popping token $end ()
Cleanup: popping nterm program ()
Starting parse <----------- **See here** ----
Entering state 0
Reading a token: Now at end of input.
Error at line 2 : syntax error
Cleanup: discarding lookahead token $end ()
Stack now 0
Unsuccessful Parse.
注意到我为您标记的那一块吗? 它说Staring parse
。 真奇怪,为什么当它刚识别出程序并到达输入结束时才开始解析? 那是因为你告诉它。 您会在主程序的摘录中注意到,我刚才调用yyparse()
两次。 一旦识别出该程序, 第二个程序尝试读取文件末尾时会给出语法错误 。
那么,您的解决方案是删除多余的yyparse()
。
十分清楚,yacc文件(第16-19行)现在显示为:
main()
{
/* yyparse(); - removed */
if (yyparse()==0)
现在很简单,不是吗? 如果您简化了代码,则可能自己找到了。 如果您使用了可用的工具,则可能自己也可以找到它。 即使您没有,通过寻求更简单代码的帮助,您也将在同一天得到答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.