【问题标题】:Why Bison always gives me "Syntax error near line x"?为什么 Bison 总是给我“第 x 行附近的语法错误”?
【发布时间】:2019-10-27 14:19:54
【问题描述】:

我目前正在从事一个 flex / bison 项目,该项目包括识别给定文件中的语法错误。 我已经编写了包含规则的解析器和 lex 文件,但我认为我有问题,因为无论我将哪个文件提供给我的程序,我都会收到以下消息 “第 1 行附近的语法错误”,即使对于像 int r1; 这样的基本行也是如此。 所以这是我的 .lex 文件,其中包含我的所有规则:

    %{
#include <stdlib.h>
#include <stdio.h>
#include "tpc-2019-2020.h"
int lineno = 1; 
%}

%option nounput
%option noinput
%x COMMENT

%%
<COMMENT>"*/" BEGIN INITIAL;
"/*" {printf("ok\n"); BEGIN COMMENT;}
"//".* ; 
<COMMENT>. ;
<COMMENT>\n ; lineno++;
int { return TYPE; }
char { return TYPE; }
";" { return 0; }
[ \t] {};
[0-9]* { return NUM; }
\n { lineno++; }
void { return VOID; }
print { return PRINT; }
while { return WHILE; }
readc { return READC; }
reade { return READE; }
[a-zA-Z] { return CHARACTER; }
[a-zA-Z][a-zA-Z0-9_]* { return IDENT; }
\+|- { return ADDSUB; }
\=\= { return EQ; }
\!\= { return EQ; }
\< { return ORDER; }
\<\= { return ORDER; }
\> { return ORDER; }
\>\= { return ORDER; }

\|\| { return OR; }
\&\& { return AND; }
. return yytext[0];

%%

还有我的 .y 文件:

%{
/* tpc-2019-2020.y */
/* Syntaxe du TPC pour le projet d'analyse syntaxique de 2019-2020*/
#include <stdio.h>
int yyparse();
int yylex();
void yyerror(char *s);
extern int lineno;
%}

%token CHARACTER
%token NUM
%token IDENT
%token TYPE
%token EQ
%token ORDER
%token ADDSUB
%token OR
%token AND
%token ELSE
%token IF
%token PRINT
%token READC
%token READE
%token RETURN
%token VOID
%token WHILE
%left ELSE 

%%
Prog:  DeclVars DeclFoncts 
    ;
DeclVars:
       DeclVars TYPE Declarateurs ';' 
    |  ;
Declarateurs:
       Declarateurs ',' IDENT 
    |  Declarateurs ',' '*' IDENT 
    |  IDENT 
    |  '*' IDENT 
    ;
DeclFoncts:
       DeclFoncts DeclFonct 
    |  DeclFonct 
    ;
DeclFonct:
       EnTeteFonct Corps 
    ;
EnTeteFonct:
       TYPE IDENT '(' Parametres ')' 
    |  TYPE '*' IDENT '(' Parametres ')' 
    |  VOID IDENT '(' Parametres ')' 
    ;
Parametres:
       VOID 
    |  ListTypVar 
    ;
ListTypVar:
       ListTypVar ',' TYPE IDENT 
    |  ListTypVar ',' TYPE '*' IDENT 
    |  TYPE IDENT 
    |  TYPE '*' IDENT 
    ;
Corps: '{' DeclVars SuiteInstr '}' 
    ;
SuiteInstr:
       SuiteInstr Instr 
    |  ;
Instr:
       LValue '=' Exp ';'
    |  READE '(' IDENT ')' ';'
    |  READC '(' IDENT ')' ';'
    |  PRINT '(' Exp ')' ';'
    |  IF '(' Exp ')' Instr 
    |  IF '(' Exp ')' Instr ELSE Instr
    |  WHILE '(' Exp ')' Instr
    |  IDENT '(' Arguments  ')' ';'
    |  RETURN Exp ';' 
    |  RETURN ';' 
    |  '{' SuiteInstr '}' 
    |  ';' 
    ;
Exp :  Exp OR TB 
    |  TB 
    ;
TB  :  TB AND FB 
    |  FB 
    ;
FB  :  FB EQ M
    |  M
    ;
M   :  M ORDER E 
    |  E 
    ;
E   :  E ADDSUB T 
    |  T 
    ;    
T   :  T '*' F 
    |  T '/' F 
    |  T '%' F 
    |  F 
    ;
F   :  ADDSUB F 
    |  '!' F 
    |  '&' IDENT 
    |  '(' Exp ')' 
    |  NUM 
    |  CHARACTER
    |  LValue
    |  IDENT '(' Arguments  ')' 
    |  '*' IDENT '(' Arguments  ')' 
    ;
LValue:
       IDENT 
    |  '*' IDENT 
    ;
Arguments:
       ListExp 
    | ;
ListExp:
       ListExp ',' Exp 
    |  Exp 
    ;
%%
int main(int argc, char** argv) {
    yyparse();
    return 0;
}
void yyerror(char *s){
    fprintf(stderr, "%s near line %d\n", s, lineno);
}

即使我的输入文件只是: int r1, r2;

它给了我“语法错误第 1 行”

我尝试只将一些 cmets 行放入我的文件中,但我收到“OK”消息,这意味着我的规则可以识别 cmets 行,但即使每次我总是收到相同的“第 1 行附近的语法错误”。

感谢您的帮助!

【问题讨论】:

    标签: bison lex


    【解决方案1】:

    您的语法表明声明如下所示:

    DeclVars:
       DeclVars TYPE Declarateurs ';' 
    

    换句话说,每个声明都以分号结尾。

    但是您的扫描仪永远不会返回分号:

    ";" { return 0; }
    

    当扫描器到达分号时,它会返回一个输入结束指示符。因此,由于缺少分号,解析失败。

    启用bison traces 会使这一点更加明显。

    【讨论】:

    • 谢谢,通过返回 yytext[0] 现在可以正常工作了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    相关资源
    最近更新 更多