YACC和LEX,在行尾获取语法错误,无法弄清楚原因

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了YACC和LEX,在行尾获取语法错误,无法弄清楚原因相关的知识,希望对你有一定的参考价值。

这是我的YACC

    %{

#include <stdio.h>
#include <ctype.h>
#include "lex.yy.c"

void yyerror (s)  /* Called by yyparse on error */
     char *s;
{
  printf ("%s
", s);
}

%}
%start program
%union{
    int value;
    char * string;
}
%token <value> NUM INT VOID WHILE IF THEN ELSE READ WRITE RETURN LE GE EQ NE
%token <string> ID
%token <value> INTEGER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS

%%
program : decllist
        {fprintf(stderr, "program");}
    ;
decllist  : dec
        {fprintf(stderr, "
 dec");}
      | dec decllist
      ;
dec : vardec
        {fprintf(stderr, "vardec");}
    | fundec
        {fprintf(stderr, "YEAH");}
    ;
typespec : INT
      | VOID
      ;
vardec  : typespec ID ';'
        {fprintf(stderr, "yep");}

    | typespec ID '[' NUM ']' ';'
        {fprintf(stderr, "again");}
    ;

fundec  : typespec ID '(' params ')' compoundstmt
    ;
params  : VOID
    | paramlist
    ;
paramlist : param
      | param ',' paramlist
      ;
param   : typespec ID
    | typespec ID '['']'
    ;
compoundstmt : '{' localdeclerations statementlist '}'
         ;
localdeclerations :/* empty */
          |vardec localdeclerations
          ;
statementlist : /* empty */
          | statement statementlist
          ;
statement : expressionstmt
      | compoundstmt
      | selectionstmt
      | iterationstmt
      | assignmentstmt
      | returnstmt
      | readstmt
      | writestmt
      ;
expressionstmt : expression ';'
           | ';'
           ;
assignmentstmt : var '=' expressionstmt
           ;
selectionstmt : IF '(' expression ')' statement
          | IF '(' expression ')' statement ELSE statement
          ;
iterationstmt : WHILE '(' expression ')' statement
          ;
returnstmt : RETURN ';'
       | RETURN expression ';'
       ;
writestmt : WRITE expression ';'
      ;
readstmt : READ var ';'
     ;

expression : simpleexpression
       ;
var : ID
    | ID '[' expression ']'
    ;
simpleexpression : additiveexpression 
         | additiveexpression relop simpleexpression
         ;
relop   : LE
    | '<'
    | '>'
    | GE
    | EQ
    | NE
    ;
additiveexpression : term
           | term addop term
           ;
addop : '+'
      | '-'
      ;
term : factor
     | term multop factor
     ;
multop : '*'
       | '/'
       ;
factor : '(' expression ')'
       | NUM
       | var
       | call
       ;
call : ID '(' args ')'
     ;
args : arglist
     | /* empty */
     ;
arglist : expression
    | expression ',' arglist
    ;
%%

main(){
yyparse();
}

这里是我的LEX

%{

int mydebug=1;
int lineno=0;
#include "y.tab.h"
%}


%%
int         {if (mydebug) fprintf(stderr, "int found
");
            return(INT);
        }
num     {if (mydebug) fprintf(stderr, "num found
");
            return(NUM);
        }
void        {if (mydebug) fprintf(stderr, "void found 
");
            return(VOID);
        }
while       {if (mydebug) fprintf(stderr, "while found 
");
            return(WHILE);
        }
if      {if (mydebug) fprintf(stderr, "if found 
");
            return(IF);
        }
then        {if (mydebug) fprintf(stderr, "then found 
");
            return(THEN);
        }
else        {if (mydebug) fprintf(stderr, "else found 
");
            return(ELSE);
        }
read        {if (mydebug) fprintf(stderr, "read found 
");
            return(READ);
        }
write       {if (mydebug) fprintf(stderr, "void found 
");
            return(WRITE);
        }

return      {if (mydebug) fprintf(stderr, "void found 
");
            return(RETURN);
        }
'<='        {if (mydebug) fprintf(stderr, "void found 
");
            return(LE);
        }
'>='        {if (mydebug) fprintf(stderr, "void found 
");
            return(GE);
        }
'=='        {if (mydebug) fprintf(stderr, "void found 
");
            return(EQ);
        }
'!='        {if (mydebug) fprintf(stderr, "void found 
");
            return(NE);
        }

[a-zA-Z][a-zA-Z0-9]*        {if (mydebug) fprintf(stderr,"Letter found
"); 
                       yylval.string=strdup(yytext); return(ID);}
[0-9][0-9]* {if (mydebug) fprintf(stderr,"Digit found
"); 
                       yylval.value=atoi((const char *)yytext); return(NUM);}
[ 	]       {if (mydebug) fprintf(stderr,"Whitespace found
");}
[=-+*/%&|()[]<>;]    { if (mydebug) fprintf(stderr,"return a token %c
",*yytext); 
                       return (*yytext);}

      { if (mydebug) fprintf(stderr,"cariage return %c
",*yytext); 
               lineno++;
                       return (*yytext);}

%%

int yywrap(void)
{ return 1;}

如果我输入'int a;'之类的东西它一直到新行并打印'回车'但后来停止并在最后吐出语法错误。谁能明白为什么?

我已经过了很多,似乎无法找到阻止它的东西。我有一个以前的程序,我要回去试图看看我是否能解决它,但我很难过。有人可以帮忙吗?

答案

你的词法分析器在行的末尾返回' '(换行符)标记,但你的解析器从不接受它们,所以当解析器命中第一个换行符时你会得到一个语法错误。

以上是关于YACC和LEX,在行尾获取语法错误,无法弄清楚原因的主要内容,如果未能解决你的问题,请参考以下文章

Yacc 与 Lex 快速入门(词法分析和语法分析)

Lex Yacc 入门

linux 下怎样安装使用 Yacc 和 Lex

Lex & Yacc

lex yacc flex bison

Lex&YACC 编译错误:在 '.' 之前应为 ')'令牌