2013-12-20 7 views
5

Ich habe ein Problem mit (Reentrant) Flex + Lemon zum Parsen. Ich benutze eine einfache Grammatik und lexer here. Wenn ich es ausführe, gebe ich eine Nummer ein, gefolgt von einem EOF-Token (Strg-D). Der Ausdruck erscheint:Lemon Parser Parsing 0 Token

89 

found int of . 
AST=0. 

Wo die erste Zeile ist die Nummer, die ich in setzen Theoretisch sollte der AST-Wert ist die Summe von allem sein, die ich in setzen

EDIT:.. Wenn ich Parse nennen () manuell wird es richtig ausgeführt.

Auch scheint Zitrone die atom ::= INT Regel auszuführen, auch wenn das Token 0 ist (das Stop-Token). Warum ist das? Ich bin sehr verwirrt über dieses Verhalten und ich kann keine gute Dokumentation finden.

Antwort

5

Okay, ich habe es herausgefunden. Der Grund ist, dass es eine besonders unangenehme (und schlecht dokumentierte) Interaktion zwischen Flex und Zitrone gibt.

In einem Versuch, Speicher zu sparen, wird Zitrone auf einem Token festhalten, ohne zu kopieren, und schieben Sie es auf einen internen Token-Stack. Flex versucht jedoch auch, Speicher zu sparen, indem er den Wert ändert, den yyget_text auf zeigt, während die Eingabe lexiert wird. Die Codezeile in meinem Beispiel ist:

// in the do loop of main.c... 
Parse(parser, token, yyget_text(lexer)); 

Dies sollte sein:

Parse(parser, token, strdup(yyget_text(lexer))); 

, die sicherstellen, dass der Wert, Zitronen-Punkte, wenn es später den Token Stapel reduziert ist das gleiche wie das, was Sie ursprünglich übergeben.

(Hinweis: Vergessen Sie nicht, strdup bedeutet, dass Sie diesen Speicher zu einem späteren Zeitpunkt freigeben müssen. Lemon können Sie Token "Destruktoren" schreiben, die dies tun können, oder wenn Sie bauen ein AST-Baum sollte bis zum Ende der AST-Lebensdauer warten.)

0

Sie können auch versuchen, einen Tokentyp zu erstellen, der einen Zeiger auf die Zeichenfolge und die Länge der Zeichenfolge enthält. Ich hatte Erfolg damit.

token.h

#ifndef Token_h 
#define Token_h 

typedef struct Token { 
    int code; 
    char * string; 
    int string_length; 
} Token; 

#endif // Token_h 

main.c

int main(int argc, char** argv) { 
    // Set up the scanner 
    yyscan_t scanner; 
    yylex_init(&scanner); 
    yyset_in(stdin, scanner); 

    // Set up the parser 
    void* parser = ParseAlloc(malloc); 

    // Do it! 
    Token t; 
    do { 
     t.code = yylex(scanner); 
     t.string = yyget_text(scanner); 
     t.string_length = yyget_leng(scanner); 
     Parse(parser, t.code, t); 
    } while (t.code > 0); 

    if (-1 == t.code) { 
     fprintf(stderr, "The scanner encountered an error.\n"); 
    } 

    // Cleanup the scanner and parser 
    yylex_destroy(scanner); 
    ParseFree(parser, free); 
    return 0; 
} 

language.y (Auszug)

class_interface ::= INTERFACE IDENTIFIER(A) class_inheritance END. 
{ 
    printf("defined class %.*s\n", A.string_length, A.string); 
} 

dort meine printf Anweisung sehen? Ich verwende die Zeichenfolge und die Länge, um mein Token auszudrucken.

Verwandte Themen