繁体   English   中英

我的yacc文件中有错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM