WebHU - Programozási kérdések és válaszok

Szintaxishiba szerzése a flex/bison nyelvtanban ezzel a nyelvtannal

Megpróbálok középső kódot generálni egy fordítóhoz. flex-bisont használok macOS-en. Amikor megpróbálok egy bevitelt, szintaktikai hibát kapok, és nem tudom, honnan származik a szintaktikai hiba.

Ez a lexem:

%{
#include<stdbool.h>
#include <stdlib.h>
#include <string.h>
//#include "LinkedList.h"
#include "parser.tab.h"
char* tempString;
%}
%option yylineno

whole   0|[1-9][0-9]*
real    {whole}\.(([0-9])|([0-9][0-9]*[1-9]))
divisionop [/]
noSymbol    [^ \t\n\/\+\-\*\:\;\,\(\)\.]
error   {noSymbol}+

%%


[ \t\n\r]+  ;



\#[-+]?{whole}/[\ :\,\;\+\-\/\*\)\n\r]|".GT."|".GE."|".EQ."|".NE."|".LT."|".LE."|":="   {

    char* string = (char*) malloc(strlen(yytext));
    strcpy(string, yytext + 1);
    string[strlen(string)] = 0;
    //printf("Found integer : %d\n", atoi(string));
    //push(string,INTEGER,yylineno);
    return INTEGER;}


\#[-+]?{real}/[\ :\,\;\+\-\/\*\)\n\r]|".GT."|".GE."|".EQ."|".NE."|".LT."|".LE."|":="    {
    char* string = (char*) malloc(strlen(yytext));
    strcpy(string, yytext + 1);
    string[strlen(string)] = 0;
    //printf("Found real:%s\n",string);
    //push(string,REAL,0);
    return REALNUM;
}

[a-zA-Z][0-9][0-9a-zA-Z]*   {
    //printf("Found identifier:%s\n",yytext);
    //yylval.str = yytext;
    //printf("****lvalue is:%s\n",yylval.str);
    //push(yytext,IDENTIFIER,yylineno);
    tempString = (char*) malloc(strlen(yytext));
    strcpy(tempString, yytext);
    return IDENTIFIER;
}

Program {
    //printf("Found program :%s\n",yytext);
    return PROGRAM;

}

Int {
    //printf("Found int :%s\n",yytext);
    return INT;

}

Real    {
    //printf("Found real :%s\n",yytext);
    return REAL;

}

Bool    {
    //printf("Found bool :%s\n",yytext);
    return BOOL;

}

Procedure   {
    //printf("Found real :%s\n",yytext);
    return PROCEDURE;

}

Function    {
    //printf("Found function :%s\n",yytext);
    return FUNCTION;

}

Begin   {
    //printf("Found begin :%s\n",yytext);
    return BEGINN;

}

End {
    //printf("Found end :%s\n",yytext);
    return END;

}

If  {
    //printf("Found if :%s\n",yytext);
    return IF;
}

Then {
    //printf("Found then :%s\n",yytext);
    return THEN;

}

Else {
    //printf("Found else :%s\n",yytext);
    return ELSE;
}

While {
    //printf("Found while :%s\n",yytext);
    return WHILE;
}

Do {
    //printf("Found do :%s\n",yytext);
    return DO;
}

For {
    //printf("Found for :%s\n",yytext);
    return FOR;
}

To {
    //printf("Found to :%s\n",yytext);
    return TO;
}

Downto {
    //printf("Found downto :%s\n",yytext);
    return DOWNTO;
}

Case {
    //printf("Found case :%s\n",yytext);
    return CASE;
}

Return {
    //printf("Found return :%s\n",yytext);
    return RETURN;
}

"And Then" {
    //printf("Found andthen :%s\n",yytext);
    //push(yytext,ANDTHEN,yylineno);
    return ANDTHEN;
}

"Or Else" {
    //printf("Found andthen :%s\n",yytext);
    //push(yytext,ORELSE,yylineno);
    return ORELSE;
}

"+" {
    //printf("Found plus :%s\n",yytext);
    return PLUS;
}

\-  {
    //printf("Found minus :%s\n",yytext);
    return MINUS;

}

\*  {
    //printf("Found multiply :%s\n",yytext);
    return MULTIPLY;
}

{divisionop}    {
    //printf("Found division :%s\n",yytext);
    //push(yytext,DIVISION,yylineno);
    return DIVISION;
}

".GT."  {
    //printf("Found greaterthan :%s\n",yytext);
    return GREATERTHAN;
}

".GE."  {
    //printf("Found greaterequal :%s\n",yytext);
    return GREATEREQUAL;
}

\.NE\.  {
    //printf("Found notequal :%s\n",yytext);
    return NOTEQUAL;
}

\.EQ\.  {
    //printf("Found EQUAL :%s\n",yytext);
    return EQUAL;
}

\.LT\.  {
    //printf("Found lessthan :%s\n",yytext);
    return LESSTHAN;
}

\.LE\.  {
    //printf("Found lessequal :%s\n",yytext);
    return LESSEQUAL;
}

[,] {
    //printf("Found comma :%s\n",yytext);
    return COMMA;
}

":="    {
    //printf("Found declare :%s\n",yytext);
    return DECLARE;
}

[:] {
    //printf("Found semicolon :%s\n",yytext);
    return COLON;
}

[;] {
    //printf("Found semicolon :%s\n",yytext);
    return SEMICOLON;
}


\( {
    //printf("Found oppar :%s\n",yytext);

    return OPPAR;

}

\)  {
    //printf("Found cppar :%s\n",yytext);
    return CPAR;
}

False   {
    //printf("Found false :%s\n",yytext);
    return FALSE;
}

True    {
    //printf("Found true :%s\n",yytext);
    return TRUE;
}

{error} {
    printf("Error on : **<<  %s  >>**\n", yytext);
    //yymore();
}
\.  {
    printf("Error on : **<<  illegal use of \" %s \" >>**\n", yytext);
    //yymore();
}

%%


int yywrap(){
    return 1;
}

//int main(){
//  yyin = fopen("input2P.txt", "r");
//  initLinkedList(table);
//  while(yylex());
//  printLinkedList();
//  return 0;
//}

ez az én elemzőm.y

%{
#include<stdio.h>
#include "stack.h"
//#include "LinkedList.h"
//#include "symbol_table.h"

int currentType;
char* returnType;

extern FILE* yyin;
extern char* tempString;
struct Stack* tblptrStack;

char* new_temp(char *c) {
    string name("t");
    name += to_string(num);
    num++;
    char *what = (char *) malloc(sizeof(char) * 100);
    strcpy(what, name.c_str());
    symbol_table_insert(what, c);
    strcpy(what, symbol_table_lookup(what).id.c_str());
    return what;
}


int yylex();
void yyerror(char* error);
struct SymbolTable* secondArg(struct SymbolTable* a,struct SymbolTable* b );
%}

%union{
  char *str;
   struct {
        int quad;
        int is_boolean;
        char *place;
        char *code;
        char *type;
   } eval;
}

}

%start program
%token INTEGER
%token ZERO
%token REALNUM
%token PROGRAM
%token INT
%token REAL
%token BOOL
%token PROCEDURE
%token FUNCTION
%token BEGINN
%token END
%token IF
%token THEN
%token ELSE
%token WHILE
%token DO
%token FOR
%token TO
%token DOWNTO
%token CASE
%token RETURN
%token ANDTHEN
%token ORELSE
%token IDENTIFIER
%token PLUS
%token MINUS
%token MULTIPLY
%token DIVISION
%token GREATERTHAN
%token GREATEREQUAL
%token NOTEQUAL
%token EQUAL
%token LESSTHAN
%token LESSEQUAL
%token COMMA
%token SEMICOLON
%token COLON
%token DECLARE
%token OPPAR
%token CPAR
%token FALSE
%token TRUE
%token ERROR
%type <eval> exp

%left COMMA
%left INT BOOL REAL

%left COLON
%left IF_PREC   
%left ELSE
%left ANDTHEN ORELSE
%left PLUS MINUS
%left MULTIPLY DIVISION
%left GREATERTHAN GREATEREQUAL NOTEQUAL EQUAL LESSTHAN LESSEQUAL

%%

program:
    PROGRAM IDENTIFIER M SEMICOLON declist block SEMICOLON {
        printf("\nin program\n"); allSymbolTablePrint( pop(tblptrStack) ); 
    }
    | PROGRAM IDENTIFIER M SEMICOLON block SEMICOLON {
        printf("\nin program\n"); allSymbolTablePrint( pop(tblptrStack) ); 
    }
    ;
M:
    { 
        struct SymbolTable* t = mkTable( NULL , "program");
        push(t, tblptrStack);
    }
;
declist:
    dec
    | declist dec 
    ;
dec : 
    vardec {printf("var deccc");}
    | procdec
    | funcdec
    ;
type : 
    INT {
        currentType=4;
        returnType = (char*) malloc(strlen("INT"));
        strcpy(returnType, "INT");
        printf("this is int");
    }
    | REAL {
        currentType=8;
        returnType = (char*) malloc(strlen("REAL"));
        strcpy(returnType, "REAL");
    }
    |BOOL {
        currentType=1;
        returnType = (char*) malloc(strlen("BOOL"));
        strcpy(returnType, "BOOL");
    }
    ;
iddec : 
    IDENTIFIER { enterVar( tempString, currentType , 0 , top(tblptrStack) ); printf("a variable entered:%s\n",tempString); }
    | IDENTIFIER { enterVar( tempString, currentType , 0 , top(tblptrStack) ); printf("a variable entered:%s\n",tempString); } DECLARE {
    printf("this is declare eeee");
    } exp 
    ;
idlist : 
    iddec {printf("this is idlist iddec");}
    | idlist COMMA iddec
    ;
vardec :
    type idlist SEMICOLON 
    {printf("vardec");}
    ;
procdec :
    PROCEDURE IDENTIFIER NP OPPAR paramdecs CPAR declist block SEMICOLON {
        char* tmpc = top(tblptrStack)->name;
        struct SymbolTable* tmpt = pop(tblptrStack);
        enterProcFunc( tmpc , 0 , "NULL" ,  tmpt , top(tblptrStack) ); 
    }
    | PROCEDURE IDENTIFIER NP OPPAR paramdecs CPAR block SEMICOLON { 
        char* tmpc = top(tblptrStack)->name;
        struct SymbolTable* tmpt = pop(tblptrStack);
        enterProcFunc( tmpc , 0 , "NULL" ,  tmpt , top(tblptrStack) ); 
    }
    ;
NP:
    {
        printf("inside NP\t tempString:%s\n",tempString);
        struct SymbolTable* t = mkTable( top(tblptrStack) , tempString );
        push(t, tblptrStack);
    }
    ;
funcdec :
    FUNCTION IDENTIFIER FN OPPAR paramdecs CPAR COLON type {
        char* tmpc = top(tblptrStack)->name;
        struct SymbolTable* tmpt = pop(tblptrStack);
        enterProcFunc(tmpc , -1 , returnType ,  tmpt , top(tblptrStack) );
    } declist block SEMICOLON
    | FUNCTION IDENTIFIER FN OPPAR paramdecs CPAR COLON type {
        char* tmpc = top(tblptrStack)->name;
        struct SymbolTable* tmpt = pop(tblptrStack);
        enterProcFunc(tmpc , -1 , returnType ,  tmpt , top(tblptrStack) );
    } block SEMICOLON
    ;
FN:
    {
        printf("inside FN\t tempString:%s\n",tempString);
        struct SymbolTable* t = mkTable( top(tblptrStack) , tempString );
        push(t, tblptrStack);
    }
    ;
paramdecs :
    paramdec { printf("paramdecs"); }
    | paramdecs SEMICOLON paramdec { printf("paramdecs\n"); }
    | { printf("paramdecs\n"); }
    ;
paramdec : 
    type paramlist
    ;
paramlist :
    IDENTIFIER 
    | paramlist COMMA IDENTIFIER
    ;
block : 
    BEGINN stmtlist END
    | stmt 
    ;
stmtlist : 
    stmt 
    | stmtlist SEMICOLON stmt 
    ;
lvalue : 
    IDENTIFIER
    ;
stmt :
    lvalue DECLARE exp 
    | IF exp THEN block %prec IF_PREC
    | IF exp THEN block ELSE block %prec ELSE
    | WHILE exp DO block 
    | FOR lvalue DECLARE exp TO exp DO block 
    | FOR lvalue DECLARE exp DOWNTO exp DO block 
    | CASE exp caseelement END 
    | RETURN exp 
    | exp {printf(stmt exp);}
    ;
exp : 
    exp ANDTHEN exp 
    | exp ORELSE exp  
    | exp PLUS exp   {
        printf("Rule  \t\t mathlogicExpression -> mathlogicExpression KW_PLUS mathlogicExpression\n");
        $$.place = new_temp($1.type);
        $$.type = $1.type;
        printf($1.place, $3.place, "+", $$.place);
    };
    | exp MINUS exp 
    | exp MULTIPLY exp { printf(" RULE FOR MULTIPLY\n");}
    | exp DIVISION exp 
    | OPPAR exp CPAR 
    | boolexp relop boolexp
    | INTEGER {printf("this is integerrrr");}
    | REALNUM 
    | TRUE
    | FALSE 
    | lvalue 
    | IDENTIFIER OPPAR explist CPAR 
    ;
boolexp:
    OPPAR exp CPAR 
    | INTEGER 
    | REALNUM 
    | TRUE
    | FALSE 
    | lvalue 
    | IDENTIFIER OPPAR explist CPAR 
    ;
caseelement : 
    INTEGER COLON block SEMICOLON
    | caseelement INTEGER COLON block SEMICOLON
    ;
explist :
    exp 
    | explist COMMA exp  
    |
    ;
relop :
    GREATERTHAN
    | GREATEREQUAL
    | NOTEQUAL
    | EQUAL
    | LESSTHAN
    | LESSEQUAL
    ;


%%

struct SymbolTable* popTop(struct Stack* b ){
    pop(b);
    top(b);
}

int main(){
    //printf("hi1");
    tblptrStack=createStack();
    tblptrStack->top = NULL;
    //printf("hi2");
    yyin = fopen("input3.txt", "r");
    //printf("hi3");
    yyparse();
    return 0;
}

void yyerror(char* error){
    printf("Error : %s\n", error);
} 

Kipróbáltam például ezt a bemenetet:

Program p1Main;

    Int i1, i2:=#-23;   
Begin
    i1 := i1 + i2;

End
;

és ezt a hibát kapom

a variable entered:i1
a variable entered:i2
Error : syntax error
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

Megpróbáltam printf s-t berakni, hogy megtudjam, honnan származik ez a szintaktikai hiba, de nem kaptam eredményt. Láttam a többi ehhez hasonló kérdést, és próbáltam a megoldásukat, de nem működött. Kérem segítsen, ha tudja, hogyan lehet ezt megoldani.


  • @Mike Kinghan köszönöm 15.05.2019

Válaszok:


1

Szintaktikai hibaüzenetet kap, mert a beviteli program szintaktikailag helytelen, és az elemző megfelelően működik.

A (kivágott) nyelvtan egy programot a következőképpen jelenít meg:

program:    PROGRAM IDENTIFIER M SEMICOLON declist block SEMICOLON

és egy blokkot jelenít meg:

block : 
    BEGINN stmtlist END
    | stmt 
    ;

és ezt követően egy nyilatkozatlista:

stmtlist : 
    stmt 
    | stmtlist SEMICOLON stmt 
    ;

Itt látni fogja, hogy a SEMIKOLTÓ egy utasításelválasztó és nem egy lezáró. Ez azt jelenti, hogy a VÉGE előtt soha nem lehet SEMIKOVESZTŐ. De ezt tetted:

 Begin
    i1 := i1 + i2;

End

Tehát el kell döntenie, melyik a nyelv helyes értelmezése; a nyelvtanod vagy a beviteli programod. A kezdők olyan gyakran követik el ezt a hibát, hogy egy tapasztalt programozónak vagy tanárnak néhány másodpercbe telik, hogy észrevegye. Hogyan használhattad a bölényt ennek megtanulására? Ezt a részletet a továbbiakban kiegészítem...


Hogyan találhattad ezt meg egyedül? Nos, a a Stack Overflow szabályainak követése jó kezdet lett volna. Nem csökkentette le a kódpéldát a probléma magyarázatához szükséges minimumra. Ön csak beledobta az EGÉSZ DOLOGOT a kérdésébe, és feladta, és átadta nekünk.

Hogyan egyszerűsíthette volna ezt a problémát egy jó tanuló. Egy dolgot tehetett volna, hogy leegyszerűsítette a tesztbevitelt az elemzőbe, és megpróbált egyszerűbb és egyszerűbb beviteli programokat. Például kérdezd meg magadtól: "A hiba a deklarációkban vagy a blokkban történik?". "Mi történik, ha egy egyszerűbb programot használok deklarációk nélkül?". Ezzel a levonási formával arra a következtetésre juthat, hogy a hiba valahol a BLOKKBAN van. Kipróbálhatott volna olyan példákat, amelyek megfeleltek a BLOCK és az utasításlista különböző szabályainak, hogy megnézze, melyik alternatíva működött, és melyik nem, és végül megtalálja azt a szabályt, amely problémákat okozott.

Ezután létrehozhatott volna egy sokkal kisebb nyelvtani, lexert és tesztprogramot, amelyet beilleszthetett volna a Stack Overflow-ba, amely megmagyarázta a konkrét problémát a hibás nyelvtani szabállyal, és ekkor kérhetett volna segítséget. Általában azonban a kisebb példa megalkotása során feltárul a probléma és a megoldás.

Hatékonyabb és programozottabb módja annak, hogy megtalálja a problémát, ha használja a bisonba épített hibakereső funkciókat. A Bisonnak van egy tesztmódja, amelyet a -t paraméterrel futtatva, valamint az yydebug változó futási időben történő beállításával engedélyezhető. Ez elkészíti az elemzés részletes nyomát, amely megmutatja, hogy pontosan melyik bemeneti szimbólum és szabály okozta a hibát. A következő részletben megmutatom, mit hoz ez...


RENDBEN. Most, miután néhány probléma a beillesztett kóddal, létrehoztam a kívánt kimenetet. Érvénytelen kódot illesztett be helytelenül a kérdésbe. Van egy extra "}" a parser.y 41. sorában, amelyet törölnöm kellett, és nincs meg a verem.h. El kellett távolítanom az összes szemantikai műveletedet, hogy megjelenjen a nyelvtani hibakeresés. Mindenesetre, miután ezt megtettük, és a bison debug engedélyezésével futtattuk, a következőket kapjuk (a Mac-en):

briantompsett:~ cssbct$ gcc parser.tab.c lex.yy.c -ll -o parser
briantompsett:~ cssbct$ ./parser
Starting parse
Entering state 0
Reading a token: Program p1Main;

    Int i1, i2:=#-23;   
Begin
    i1 := i1 + i2;

End
;Next token is token PROGRAM ()
Shifting token PROGRAM ()
Entering state 1
Reading a token: Next token is token IDENTIFIER ()
Shifting token IDENTIFIER ()
Entering state 3
Reducing stack by rule 3 (line 108):
-> $$ = nterm M ()
Stack now 0 1 3
Entering state 5
Reading a token: Next token is token SEMICOLON ()
Shifting token SEMICOLON ()
Entering state 6
Reading a token: Next token is token INT ()
Shifting token INT ()
Entering state 9
Reducing stack by rule 9 (line 122):
   $1 = token INT ()
-> $$ = nterm type ()
Stack now 0 1 3 5 6
Entering state 26
Reading a token: Next token is token IDENTIFIER ()
Shifting token IDENTIFIER ()
Entering state 50
Reading a token: Next token is token COMMA ()
Reducing stack by rule 12 (line 133):
   $1 = token IDENTIFIER ()
-> $$ = nterm iddec ()
Stack now 0 1 3 5 6 26
Entering state 51
Reducing stack by rule 15 (line 139):
   $1 = nterm iddec ()
-> $$ = nterm idlist ()
Stack now 0 1 3 5 6 26
Entering state 52
Next token is token COMMA ()
Shifting token COMMA ()
Entering state 82
Reading a token: Next token is token IDENTIFIER ()
Shifting token IDENTIFIER ()
Entering state 50
Reading a token: Next token is token DECLARE ()
Shifting token DECLARE ()
Entering state 81
Reducing stack by rule 13 (line 134):
-> $$ = nterm @1 ()
Stack now 0 1 3 5 6 26 52 82 50 81
Entering state 110
Reading a token: Next token is token INTEGER ()
Shifting token INTEGER ()
Entering state 7
Reading a token: Next token is token SEMICOLON ()
Reducing stack by rule 52 (line 206):
   $1 = token INTEGER ()
-> $$ = nterm exp ()
Stack now 0 1 3 5 6 26 52 82 50 81 110
Entering state 124
Next token is token SEMICOLON ()
Reducing stack by rule 14 (line 134):
   $1 = token IDENTIFIER ()
   $2 = token DECLARE ()
   $3 = nterm @1 ()
   $4 = nterm exp ()
-> $$ = nterm iddec ()
Stack now 0 1 3 5 6 26 52 82
Entering state 111
Reducing stack by rule 16 (line 140):
   $1 = nterm idlist ()
   $2 = token COMMA ()
   $3 = nterm iddec ()
-> $$ = nterm idlist ()
Stack now 0 1 3 5 6 26
Entering state 52
Next token is token SEMICOLON ()
Shifting token SEMICOLON ()
Entering state 83
Reducing stack by rule 17 (line 143):
   $1 = nterm type ()
   $2 = nterm idlist ()
   $3 = token SEMICOLON ()
-> $$ = nterm vardec ()
Stack now 0 1 3 5 6
Entering state 27
Reducing stack by rule 6 (line 117):
   $1 = nterm vardec ()
-> $$ = nterm dec ()
Stack now 0 1 3 5 6
Entering state 25
Reducing stack by rule 4 (line 113):
   $1 = nterm dec ()
-> $$ = nterm declist ()
Stack now 0 1 3 5 6
Entering state 24
Reading a token: this is idlist iddecthis is declare eeeethis is integerrrrvardecvar decccNext token is token BEGINN ()
Shifting token BEGINN ()
Entering state 14
Reading a token: Next token is token IDENTIFIER ()
Shifting token IDENTIFIER ()
Entering state 20
Reading a token: Next token is token DECLARE ()
Reducing stack by rule 34 (line 184):
   $1 = token IDENTIFIER ()
-> $$ = nterm lvalue ()
Stack now 0 1 3 5 6 24 14
Entering state 31
Next token is token DECLARE ()
Shifting token DECLARE ()
Entering state 54
Reading a token: Next token is token IDENTIFIER ()
Shifting token IDENTIFIER ()
Entering state 20
Reading a token: Next token is token PLUS ()
Reducing stack by rule 34 (line 184):
   $1 = token IDENTIFIER ()
-> $$ = nterm lvalue ()
Stack now 0 1 3 5 6 24 14 31 54
Entering state 39
Next token is token PLUS ()
Reducing stack by rule 56 (line 210):
   $1 = nterm lvalue ()
-> $$ = nterm exp ()
Stack now 0 1 3 5 6 24 14 31 54
Entering state 84
Next token is token PLUS ()
Shifting token PLUS ()
Entering state 57
Reading a token: Next token is token IDENTIFIER ()
Shifting token IDENTIFIER ()
Entering state 20
Reading a token: Next token is token SEMICOLON ()
Reducing stack by rule 34 (line 184):
   $1 = token IDENTIFIER ()
-> $$ = nterm lvalue ()
Stack now 0 1 3 5 6 24 14 31 54 84 57
Entering state 39
Next token is token SEMICOLON ()
Reducing stack by rule 56 (line 210):
   $1 = nterm lvalue ()
-> $$ = nterm exp ()
Stack now 0 1 3 5 6 24 14 31 54 84 57
Entering state 87
Next token is token SEMICOLON ()
Reducing stack by rule 46 (line 200):
   $1 = nterm exp ()
   $2 = token PLUS ()
   $3 = nterm exp ()
-> $$ = nterm exp ()
Stack now 0 1 3 5 6 24 14 31 54
Entering state 84
Next token is token SEMICOLON ()
Reducing stack by rule 35 (line 187):
   $1 = nterm lvalue ()
   $2 = token DECLARE ()
   $3 = nterm exp ()
-> $$ = nterm stmt ()
Stack now 0 1 3 5 6 24 14
Entering state 38
Reducing stack by rule 32 (line 180):
   $1 = nterm stmt ()
-> $$ = nterm stmtlist ()
Stack now 0 1 3 5 6 24 14
Entering state 37
Next token is token SEMICOLON ()
Shifting token SEMICOLON ()
Entering state 71
Reading a token: Next token is token END ()
Error : syntax error
Error: popping token SEMICOLON ()
Stack now 0 1 3 5 6 24 14 37
Error: popping nterm stmtlist ()
Stack now 0 1 3 5 6 24 14
Error: popping token BEGINN ()
Stack now 0 1 3 5 6 24
Error: popping nterm declist ()
Stack now 0 1 3 5 6
Error: popping token SEMICOLON ()
Stack now 0 1 3 5
Error: popping nterm M ()
Stack now 0 1 3
Error: popping token IDENTIFIER ()
Stack now 0 1
Error: popping token PROGRAM ()
Stack now 0
Cleanup: discarding lookahead token END ()
Stack now 0

Látni fogja, hogy most a VÉGE előtt megállt a SEMIKOLONS-nál, amint azt a nyomkövetés ezen része mutatja:

Next token is token SEMICOLON ()
Shifting token SEMICOLON ()
Entering state 71
Reading a token: Next token is token END ()
Error : syntax error
Error: popping token SEMICOLON ()

Így kell hibakeresést végezni a jövőben.

15.05.2019
  • Kiváló válasz! 15.05.2019
  • Köszönöm szépen a részletes választ, nagyon hálás vagyok a segítségért. @Brian Tompsett - 汤莱恩. Lenne egy olyan kérdésem, hogy amikor a gcc parser.tab.c lex.yy.c -ll -o parser -t használtad, beírtad az összes Stack now,Cleanup,... elemet az értelmezőbe? mert amikor futtatom az elemzőt, nem jelenít meg olyan részleteket, mint a Token olvasása, Belépés, ... fordítóprogramot írok így. köszönöm szépen a segítséget 16.05.2019
  • @MelikaKnight Kérjük, kattintson a pipa szimbólumra a válasz elfogadásához. BTW: Az elemző példányomban nincs veremkód. Ahogy mondtam, letöröltem, hogy lefordítható legyen. 16.05.2019
  • @BrianTompsett-汤莱恩, jó munkát! Valójában többet dolgoztál, mint az eredeti kérdésplakát. 17.05.2019
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..