Wie kann ich drucken, was ich sehe, in Yacc/Bison?

Ich habe eine komplizierte Yacc-Datei mit einer Reihe von Regeln, einige von Ihnen kompliziert, zum Beispiel:

start: program
program: extern_list class
class: T_CLASS T_ID T_LCB field_dec_list method_dec_list T_RCB

Die genauen Regeln und die Aktionen, die ich nehme an, Sie sind nicht wichtig, weil das, was ich will zu tun, scheint ziemlich einfach: drucken Sie das Programm, wie Sie in der Quelldatei, indem Sie die Regeln bestimme ich für andere Zwecke. Aber ich bin überrascht, wie schwierig dies ist.

Zuerst habe ich versucht, indem printf("%s%s", $1, $2) für die zweite Regel oben. Diese produziert „��@P�@“. Von dem was ich verstehe, der Analysierte text ist auch verfügbar als eine variable, yytext. Ich fügte printf("%s", yytext) zu jeder Regel in der Datei Hinzugefügt extern char* yytext; an den Anfang der Datei. Diese produziert (null){void)1133331122222210101010--552222202020202222;;;;||||&&&&;;;;;;;;;;}}}}}}}} aus einer gültigen Datei nach der Sprache der syntax. Schließlich änderte ich extern char* yytext; zu extern char yytext[], dachte, es würde keinen Unterschied machen. Der Unterschied in der Ausgabe, die es gemacht ist am besten als screenshotWie kann ich drucken, was ich sehe, in Yacc/Bison?

Ich bin mit Bison-3.0.2 auf Xubuntu 14.04.

InformationsquelleAutor EMBLEM | 2016-03-07

 

2 Replies
  1. 2

    Wenn Sie nur wollen auf der echo-Quelle, um eine Ausgabe während der Analyse, es ist am einfachsten zu tun, dass in den lexer. Was du nicht sagst, was du ware für eine lexer, aber Sie erwähnen yytext zu, die von lex/flex, also gehe ich davon aus, dass.

    Wenn Sie verwenden Sie flex zum erkennen von Token, die variable yytext bezieht sich auf die internen Puffer verwendet flex zu erkennen Token. Innerhalb der Aktion eines Tokens, kann es verwendet werden, um den text des Tokens, aber nur vorübergehend-sobald die Aktion abgeschlossen ist und das nächste token gelesen wird, es wird nicht mehr gültig sein.

    Also, wenn Sie einen flex-Regel wie:

    [a-zA-Z_][a-zA-Z_0-9]*    { yylval.str = yytext, return T_ID; }

    dass wahrscheinlich nicht alle, da musst du baumelnden Zeiger laufen um in Ihrem Programm; wahrscheinlich die Quelle der random-Suche-Ausgänge, die Sie sehen. Stattdessen müssen Sie eine Kopie zu machen. Wenn Sie auch wollen, um die Ausgabe der input unverändert, Sie können tun, dass sich auch hier:

    [a-zA-Z_][a-zA-Z_0-9]*    { yylval.str = strdup(yytext); ECHO; return T_ID; }

    Diese nutzt die flex-makro ECHO das entspricht ungefähr fputs(yytext, yyout) – das kopieren der Eingabe auf FILE * genannt yyout (standardmäßig stdout)

  2. 2

    Wenn das erste symbol in der entsprechenden rechten Seite befindet sich ein terminal, $1 in einem bison-Aktion bedeutet, „den Wert von yylval vom scanner erzeugte, wenn es wieder in die entsprechenden token, terminal. Wenn das symbol ist ein nicht-terminal, dann bezieht es sich auf den Wert $$ bei der Bewertung der Maßnahmen, die stark reduziert ist, dass nicht-terminal. Wenn es keine solche Aktion, dann die Standard – $$ = $1 wurden durchgeführt, so wird durch die semantische Wert des ersten symbols in der Reduktion der nicht-terminal.

    Ich entschuldige mich, wenn alle das war klar, aber das snippet ist nicht ausreichend, um zu zeigen:

    • was die semantischen Typen sind für jedes nicht-terminal;

    • was die semantischen Typen sind für jedes terminal;

    • welche Werte werden, falls vorhanden, zugeordnet yylval im scanner-Aktionen;

    • welche Werte werden, falls vorhanden, zugeordnet $$ in der bison-Aktionen.

    Wenn diese semantischen Typen sind nicht in der Tat, Zeichenketten, dann die printf wird offensichtlich produzieren Müll. (gcc könnte in der Lage sein, um Sie zu warnen, über diese, wenn Sie kompilieren Sie den generierten code mit -Wall. Trotz der Möglichkeit der unechten Warnungen, wenn Sie mit alten Versionen von flex/bison, ich denke, es ist immer lohnt sich kompilieren mit -Wall sorgfältig und Lesen Sie die resultierende Warnungen.)

    Mit yytext in einem bison-Aktion ist problematisch, da es bezieht sich auf den text der letzten token gescannt, in der Regel die look-ahead-token. Insbesondere am Ende der Eingabe yytext wird NULL, und das ist, was Sie abholen in alle Reduktionen, die auftreten, an das Ende der Eingabe. glibc ist printf Umsetzung ist schön genug, um zu drucken (null) statt segfaulting wenn Ihr (char*)0 zu einem argument formatiert %s, aber ich glaube nicht, dass es eine gute Idee, abhängt.

    Schließlich, wenn Sie haben ein char* semantischen Wert, und weisen Sie yylval = yytext (oder yylval.sval = yytext; wenn Sie mit Gewerkschaften), dann läuft man in ein weiteres problem, welches ist, dass yytext Punkte in einem temporären Puffer im Besitz der scanner, und die Puffer können völlig unterschiedliche Inhalte haben, von der Zeit bekommen Sie rund um die Adresse. So benötigen Sie immer eine Kopie der yytext wenn Sie möchten, führen Sie es durch den parser.

    Wenn das, was Sie wirklich wollen, zu tun ist, sehen, was der parser ist zu tun, ich schlage vor, Sie aktivieren bison yydebug parser-trace-Funktion. Es wird Ihnen eine Menge nützlicher Informationen, ohne dass Sie zum einfügen von printf ist in Ihrer bison-Aktionen überhaupt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.