2016-11-02 3 views
0

Ich habe Scanner und Parser bereit, mit Flex und Bison.Access Identifier Inhalt bei Verwendung eines benutzerdefinierten Typs in Bison

Der Parser baut einen Baum direkt in den Aktionen, und zu tun, so habe ich eine Struktur namens STreeNode und ich bin mit

#define YYSTYPE_IS_DECLARED 
typedef STreeNode* YYSTYPE; 

Die Struktur ist:

typedef struct tagSTreeNode 
{ 
    EOperationType type; 
    int count; 
    struct tagSTreeNode **children; 
    char *string; 
} STreeNode; 

Es gibt wie 40 Tokens, und für jede Regel habe ich etwas wie

unlabeled_statement: 
     assignment               {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | function_call_statement           {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | goto                {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | return               {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | conditional              {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | repetitive              {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | empty_statement             {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     ; 

Die Signatur für die createNode-Funktionen auf ist

STreeNode *createNode(EOperationType type, int count, ...) { 

Der Baum funktioniert gut. Das Problem besteht darin, auf den tatsächlichen Wert für Variablennamen, Funktionsnamen usw. zuzugreifen. Da YYSTYPE eine Struktur ist, hat $ x nicht den Zeichenfolgenwert, den ich für das char * string-Element in der Struktur speichern möchte.

Ich habe ein% Token namens IDENTIFIER und ein anderes namens INTEGER, und diese sollten die Werte erhalten, die ich will.

Nachforschungen, ich entdeckte, dass ich versuchen konnte, eine Union {} zu verwenden, um jedes Token eines bestimmten Typs zu haben. Vielleicht könnte das helfen? Und wenn ja, müsste ich unbedingt den Typ jedes einzelnen Tokens angeben? Wie kann das implementiert werden?

Was ist mit yytext? Könnte das nicht zur Erreichung dieses Ziels verwendet werden?

Vielen Dank!

--- EDIT -

Also habe ich erstellt

%union { 
    char *string; 
    STreeNode *node; 
} 

und spezifiziert jede Klemme und nicht Terminal-Typ einer von denen zu sein. Die Knoten funktionieren noch, aber die Strings, die (zum Beispiel $ 1) verwenden, geben null zurück.

Muss ich auch etwas am Scanner ändern? Mein Scanner hat:

[a-zA-Z][a-z0-9A-Z]*  { return IDENTIFIER; } 
[0-9]+      { return INTEGER; } 

Danke nochmal.

+0

Wenn Sie Bison verwenden, warum ist dies markiert "yacc"? –

+0

Nur eine kleine Frage, die nichts mit Ihrem Problem zu tun hat, aber warum erstellen Sie Knoten für Dinge, die sie nicht brauchen? Anstatt einen neuen Knoten für 'conditioal' zu erstellen, muss man einfach' $$' auf '$ 1' setzen. Das wird Ihren Baum ein wenig vereinfachen und zu viel weniger Knoten führen. –

+0

@ScottHunter Das 'flex'-Tag ist für [Apache Flex] (http://flex.apache.org/) nicht der GNU-Lex-Klon, also habe ich es entfernt. –

Antwort

0

Wenn für Ihre Token ein Typ festgelegt ist, muss der Lexer yylval auf den betreffenden Typ setzen. Etwas wie:

[a-zA-Z][a-z0-9A-Z]*  { yylval.string = strdup(yytext); return IDENTIFIER; } 
[0-9]+      { yylval.string = strdup(yytext); return INTEGER; } 
Verwandte Themen