2016-09-18 18 views
0

Zum Beispiel erzeugt Laufen ich den Code habenUnexpected Syntaxfehler erzeugt durch YACC Parser

%nonassoc lower 
%nonassoc ELSE 

if_stmt: IF '(' expr ')' statement %prec lower 
     { 
      /*some code*/ 
     } 
     | IF '(' expr ')' statement ELSE statement 
     { 
      /*some code*/ 
     } 
     ; 

Mit den Regeln und der Code (die nicht viel tun) ich jetzt bekommen „elsesyntaxFehler“, wenn Ich teste eine IF-ELSE-Anweisung. Wenn es nur eine IF-Anweisung ist, funktioniert es gut.

Ich dachte, dass ich etwas in der zweiten Aktion übergeben sollte, damit es funktioniert, aber ich bin mir nicht sicher was.

Wenn möglich, möchte ich die 2 Aktionen nicht trennen.

EDIT: Also hier ist die Grammatik wie gefragt, und die Priorität: EDIT2: implementiert meine Grammatikregeln. compound_stmt und local_declarations sind Kommentare, weil ich noch nicht weiß, was ich mit ihnen machen soll.

%nonassoc islowerthanelse 
%nonassoc ELSE 

%% 

%token <intVal> NUM WHILE PRINT IF ELSE INT 

program   : declaration_list statement_list  
         { 
         printf("/0\n"); 

         } 
         ;          

declaration_list : declaration_list declaration   
          { 
          printf("/1\n"); 
          $$ = make_node(DeclSeq, NULL, $1, $2, NULL, NULL); 
          } 
         |declaration 
         { 
          printf("/2\n"); 
          $$ = $1; 
         }       
         ; 

declaration  : type_specifier ID ';'     
          { 
          printf("/3\n"); 
          $$ = make_node(Decl, p3, $1, NULL, NULL, NULL); 
          } 

type_specifier  : INT         
          { 
          printf("/5\n"); 
          $$ = make_node(INT, NULL, NULL, NULL, NULL, NULL); 

          } 
         ; 

statement_list  : statement_list statement    
         { 
          printf("/6\n"); 
          $$ = make_node(StmtSeq, NULL, $1, $2, NULL, NULL); 
         } 
         |/* EMPTY */ 
          { 
          printf("/7\n"); 
          $$ = make_node(astEmptyStmtSeq, NULL, NULL, NULL, NULL, NULL); 

          } 
         ; 

statement   : expression_stmt      
          { 
          printf("/8\n"); 
          $$ = $1; 
          } 
         /*|compound_stmt      
          { 
          $$ = $1; 
          }*/ 
         |selection_stmt      
          { 
          $$ = $1; 
          } 
         |iteration_stmt      
          { 
          $$ = $1; 
          } 
         |print_stmt       
          { 
          printf("/12\n"); 
          $$ = $1; 
          } 
         ; 

/*compound_stmt  : '{' local_declarations statement_list '}' 
         ; 

local_declarations : local_declarations declaration 
         |/* EMPTY *\ 
         ;*/ 

expression_stmt : expression ';'      
          { 
          printf("/15\n"); 
          $$ = make_node(ExprStmt, NULL, $1, NULL, NULL, NULL); 
          }     
         |/* EMPTY */ ';' 
          { 
          printf("/16\n"); 
          $$ = make_node(EmptyExprStmt, NULL, NULL, NULL, NULL, NULL); 
          } 
         ; 

selection_stmt  : IF '(' expression ')' statement  %prec islowerthanelse  
          { printf("/256\n"); 
          $$ = make_node(IfStmt, NULL, $3, $5, NULL, NULL); 

          }  
         |IF '(' expression ')' statement ELSE statement 
          {printf("/257\n"); 
          $$ = make_node(IfElseStmt, NULL, $3, $5, $7, NULL); 
          }      
         ; 

iteration_stmt  : WHILE '(' expression ')' statement 
          { 
          $$ = make_node(astWhileStmt, NULL, $3, $5, NULL, NULL); 
          } 
          ; 
+1

Diagnostizieren yacc/Bison Grammatik Probleme ist fast unmöglich, ohne die vollständige Grammatik zu sehen. Sie müssen eine [MVCE] (http://stackoverflow.com/help/mcve) veröffentlichen, wenn Sie nützliche Hilfe erhalten möchten. –

+0

Ich denke, Ihr "Grammatik und Vorrang" -Abschnitt zeigt, was Sie implementieren sollen, während das Problem in dem ist, was Sie implementieren. Wir müssen wahrscheinlich eine minimale Version Ihrer Yacc-Grammatik sehen, die das Problem reproduziert (siehe [MCVE]). Das Problem tritt zur Laufzeit auf, glaube ich. Das heißt, Ihre Grammatik kompiliert und die Programmverknüpfungen, aber Sie erhalten einen unerwünschten Fehler, wenn Sie es auf einer IF/ELSE-Anweisung ausführen - ist das richtig? –

+0

@JonathanLeffler Ich verbinde nicht etwas, ist das falsch? Ich lexiere den Lexer, yacc den Parser, gcc die .c-Dateien und mit der .exe-Datei habe ich Code zum Testen hinzugefügt. – codeNewbie

Antwort

0

Aktionen sind unabhängig voneinander; es gibt kein "Durchfallen". Wenn Sie den gemeinsamen Code zwischen zwei Aktionen umgestalten wollen, stellen Sie ihn in eine Funktion, die von den Aktionen aufgerufen werden kann.

Das sollte jedoch nichts mit dem Syntaxfehler zu tun haben, den Sie sehen. Aktionen haben keinen Einfluss auf die Analyse. Wenn der Parser einen Syntaxfehler meldet, führt er dies aus, ohne eine Aktion auszuführen (da der Fehler die Unmöglichkeit widerspiegelt, eine geeignete Produktion zu finden).

+0

also, da die produktion da ist, wie kann ich es sehen lassen? – codeNewbie

+0

@codeenewbie: Ich bin sicher, dass Bison die Produktion sieht :) Es gibt ein Problem in Ihrer Grammatik, aber wir müssten mehr als eine Regel sehen, um zu sagen, was es ist. [mcve] – rici

+0

Ich habe meine Frage mit einigen meiner Grammatikregeln bearbeitet (falls Sie beim Bearbeiten nicht bemerkt werden, wissen Sie nicht, wie es funktioniert) – codeNewbie

0

beste Vermutung aus dem Show-Fragmente - Ihr %prec lower hat tatsächlich eine höhere Priorität, die die ELSE Token, also wenn ein ELSE sehen wird es die erste Regel zu reduzieren, und dann einen Syntaxfehler erhalten, da sie nicht alles tun kann, mit die ELSE nach der Reduktion.

Um diese Frage beantworten zu können, müsste man jedoch die vollständige Grammatik sehen.


Ich habe folgendes auf Ihre Grammatik eine MVCE zu machen:

%{ 
#include <stdio.h> 
#define make_node(...) 0 
%} 

%nonassoc islowerthanelse 
%nonassoc ELSE 

%token NUM WHILE PRINT IF INT ID 
%token expression print_stmt 

%% 

:

%% 
#include "lex.yy.c" 
int main() { return yyparse(); } 
int yywrap() { return 1; } 
void yyerror(const char *msg) { printf("%s\n", msg); } 

Zusammen mit einem trivialen Lexer:

%% 
"while" return WHILE; 
"print" return PRINT; 
"if" return IF; 
"else" return ELSE; 
"int" return INT; 
"expression" return expression; 
[A-Za-z][A-Za-z0-9]* return ID; 
[0-9]* return NUM; 
[ \t\n] ; 
. return *yytext; 

und einen Eingang Datei wie:

int A; 
if (expression) expression; else expression; 

und es scheint ganz gut zu funktionieren ...

$ a.out <input.txt/5 
/3 
/2 
/7 
/15 
/8 
/15 
/8 
/257 
/6 
/0 
+0

Wenn ich die notwendigen fehlenden Sachen hinzufüge, um Ihre Grammatik zu kompilieren und auszuführen (einfach lexer/main/fehlende Deklarationen) es analysiert ein if/sonst gut. –

+0

Würden Sie so freundlich sein, Beispielcode zu posten? Ich habe immer noch das gleiche Problem mit einer if-else-Anweisung.Ich bin ein wenig unter Druck, deshalb kann ich selbst kein minimales Beispiel geben. – codeNewbie

Verwandte Themen