Почему Бизон всегда дает мне «Синтаксическая ошибка возле строки x»? - PullRequest
0 голосов
/ 27 октября 2019

В настоящее время я работаю над проектом 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»

Я попытался поместить только несколько строк комментариев в свой файл, и я получил сообщение «ОК», что означаетмои правила распознают строки комментариев, но даже если я всегда получаю одну и ту же «Синтаксическую ошибку около строки 1» каждый раз.

Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 27 октября 2019

Ваша грамматика говорит, что объявление выглядит так:

DeclVars:
   DeclVars TYPE Declarateurs ';' 

Другими словами, каждое объявление заканчивается точкой с запятой.

Но ваш сканер никогда не возвращает точку с запятой:

";" { return 0; }

Когда сканер достигает точки с запятой, он возвращает индикатор конца ввода. Таким образом, анализ не выполняется из-за отсутствия точки с запятой.

Включение следов бизонов сделает это более очевидным.

...