2013-02-01 4 views
5

Wenn Sie eine ("theoretische") Grammatik mit einer Regel mit einer leeren rechten Seite schreiben, verwenden Sie immer ein Symbol wie ε (oder 1), um diese Leerstelle explizit zu machen :Eine Notation für leere rechte Seiten der Regeln

A → ε | a A 

eine solche Grammatik in Yacc und andere aussehen würde dann wie

a: | 'a' a 

oder "schlechter"

a:  { $$ = new_list(); } 
| a 'a' { $$ = $1; $$->append($1); } 
; 

Die Tatsache, dass in "Realwelt-Grammatiken" (Yacc, Bison usw.) dieser leere rechte Teil der Regel nicht explizit als leer markiert ist, beunruhigt mich: Es ist leicht zu übersehen, dass ein rhs leer ist, oder schlimmer : vergessen | einzusetzen und verwenden tatsächlich eine Aktion Mitte der Regel:

a:  { $$ = new_list(); } 
    a 'a' { $$ = $1; $$->append($1); } 
; 

1) ich von Werkzeug nicht wissen, dass sie zu einem leeren rhs explizit machen bietet. Sind da irgendwelche?

Zukünftige Versionen von Bison unterstützen möglicherweise ein dediziertes Symbol mit Fehlern, wenn es in einer nicht leeren rhs verwendet wird, und Warnungen, wenn eine implizit leere rhs übrig ist.

2) Halten die Leute das für nützlich?

3) Welche Schreibweise würden Sie vorschlagen?

Derzeit ist der Kandidat $empty:

a: $empty { $$ = new_list(); } 
| a 'a' { $$ = $1; $$->append($1); } 
; 

EDIT

Die gewählte Syntax ist %empty:

a: %empty { $$ = new_list(); } 
| a 'a' { $$ = $1; $$->append($1); } 
; 

Tat $empty sieht aus wie ein pseudo-Symbol, wie $accept dass Bison generiert für die erste Regel oder die [email protected] Pseudosymbole für Mid-Regel-Aktionen oder $eof für, nun, Ende der Datei. Aber es ist definitiv kein Symbol, es ist gerade die Abwesenheit von Symbolen.

Auf der anderen Seite bezeichnet % eindeutig eine Direktive (irgendeine Art von Attribut/Metadaten), wie %pred.

Es ist also ein kleiner Unterschied der Syntax, aber es ist mehr konsistent mit der Gesamtsyntax. Der Dank geht an Joel E. Denny.

Antwort

0

Ich habe epsilon selbst verwendet, sowie Variationen über für leere Produktionen, an die ich etwas Code in geschweiften Klammern anschloss.

Ein reserviertes Symbol in der Bison-Grammatik wäre nützlich; Ich mag das vorgeschlagene $ Präfix, um Kollisionen mit benutzerdefinierten Symbolen zu vermeiden.

+0

Danke. Wir werden wahrscheinlich '% empty' stattdessen verwenden (als ein Pseudosymbol, nicht als eine Direktive, wie von Chris in seiner Antwort vorgeschlagen), da es wirklich ein Schlüsselwort ist, kein Symbol (es ist kein Terminal, wie' $ end ', noch ein Nichtterminal, wie' $ accept'). – akim

0

1) Nun gibt es die offensichtliche

 
e: a 'b' 
a: 'a' 
| empty 
empty: 

2) Ja, das wäre sehr hilfreich sein.

3) Die $accept, $end und $undefined Symbole immer definiert sind, und für Bison internen Gebrauch ausschließlich (zB vorbehalten., Können sie nicht in der Grammatik erscheinen). Bison generiert [email protected] für Mid-Rule-Aktionen, aber diese können auch nicht in der Grammatik des Benutzers verwendet werden.

Das einzige vordefinierte Token, das der Benutzer in der Grammatik verwenden kann, wenn ich mich nicht irre, ist error. Warum schlagen Sie nicht empty für dieses dedizierte Symbol vor? Das wäre ziemlich vernünftig erschienen. Oder schlagen Sie vor, auch $error einzuführen?

Haben Sie in Betracht gezogen nothing? Das könnte ich lieber.

+1

Ihr Vorschlag ist nicht derselbe wie meiner: Ihr Parser wird mehr Zustände haben, um Ihr "leeres" Nicht-Terminal zu reduzieren (zwei Reduktionen am Ende, während die ursprüngliche Grammatik nur eins hätte). Es ist einfach, den Unterschied zu sehen, wenn Sie Aktionen hinzufügen: Sie haben zwei, ich habe eine. – akim

5

ich in der Regel nur einen Kommentar verwenden:

a: /*epsilon*/ { $$ = new_list(); } 
| a 'a' { $$ = $1; $$->append($1); } 
; 

ohne Änderungen Adaequat und macht die Absicht klar ....

IMO, kommt dies der Überschrift unter „Wenn es nicht kaputt ist , nicht fix it“

+0

Ich benutze auch einen Kommentar, und ich kann mich nicht erinnern, einen solchen Fehler gemacht zu haben. Dennoch habe ich gesehen, dass Schüler auf verschiedene Arten scheitern, ich bevorzuge explizite statt implizite (ich verwende einen Kommentar, weil es keine Alternative gibt), und ich bevorzuge auch Prüfungen so früh wie möglich (Kompilierzeit statt Laufzeit). – akim

2

ich würde vorschlagen, die folgenden:

definieren sie die Erklärung:

%empty ID 

deren Semantik sind zweifach:

1) ID kann als die einzigen nicht-Token-Regel in einer RHS verwendet werden, um anzuzeigen, dass die RHS eine epsilon-Produktion ist; und

2) Epsilon-Produktionen, die nicht mit ID markiert sind, gelten als Syntaxfehler.

So mit der Erklärung:

%empty epsilon 

epsilonMuss verwendet werden, um eine leere RHS zu markieren; ohne eine %empty Deklaration, der Status quo gilt, wo leere RHS nicht markiert sind (außer vielleicht mit Kommentaren).

Das würde es Benutzern, die gerne leere RHS explizit markieren, ermöglichen, dies sofort zu tun, ohne irgendwelche Auswirkungen auf vorhandene Grammatikdateien oder Benutzer zu haben, die nicht leere RHS auf diese Weise explizit markieren möchten.

Persönlich würde ich wahrscheinlich eine solche Erklärung verwenden, obwohl um ehrlich zu sein bin ich ziemlich gewöhnt, einen Kommentar zu verwenden, um eine leere RHS zu markieren, und ich glaube nicht, dass ich jemals versehentlich eine leere RHS gemacht habe. Also würde ich es nicht als eine vorrangige Feature-Anfrage markieren, aber ich würde auch nichts gegen seine Implementierung einwenden.

+0

Die Verwendung einer Direktive ist eine interessante Idee! Aber es scheint, als ob Sie glauben, dass es ein Fehler wäre, '$ empty' nicht zu verwenden: das ist nicht meine Absicht, es wäre nur eine Warnung,' -Wempty', die standardmäßig deaktiviert ist. Aber ich bevorzuge einen eindeutigen Namen für das Schlüsselwort empty, damit jemand, der die Grammatik einer anderen Person liest, nicht mit der Natur dieses Pseudo-Tokens verwechselt wird. – akim

+0

Hallo! Nun, ich habe eine völlig andere Meinung zu Warnungen. Ich benutze dann ausgiebig, in vielen Projekten (freie Software, aber auch in Closed-Source-Software). Ich habe jedoch nicht vor, diese Warnung standardmäßig zu aktivieren. Aber, IIUC, deine Sorgen, es wäre vernünftig, fehlende leere Marker zu diagnostizieren, wenn es in einer Regel verwendet wurde, oder? Das würde die Konsistenz erzwingen: entweder ganz oder gar nicht. Macht viel Sinn! – akim

+0

@akim: Ohne die Deklaration ist es nicht möglich anzugeben, dass eine leere Produktion ein Fehler sein sollte, es sei denn, es gibt mindestens eine leere Produktion. Wenn ich also eine Grammatik habe, die keine leeren Produktionen haben sollte (ein häufiger Fall), hilft mir die Konsistenzprüfung nicht. Aber ich werde es dabei belassen. Wie gesagt, ich habe nicht das Gefühl, dass diese Funktion eine Priorität ist, und ich bin geneigt, mit "wenn es nicht kaputt ist, mach es nicht". – rici

0

Natürlich ist die Produktion in gewissem Sinne nicht wirklich "leer", wenn sie eine Aktion enthält, da es in Yacc/Bison schwer ist, die Tatsache nicht zu ahnen, dass Aktionen hinter den Kulissen in nullbare Nicht-Terminals umgewandelt werden. Und wenn Sie (oder das Buch) während des Semesters in der Klasse "epsilon" gesagt haben, hat "% epsilon" vielleicht mehr Wahrscheinlichkeit als "% empty".

sinne ich über diese in eine allgemeinere Behauptung Mechanismus zu subsumieren:

lines : %assert(epsilon) 
     | %assert(on WORD) lines line ; 

line : WORD '\n' ; 

%assert(nullable(lines)) 
%assert(!nullable(line)) 
%assert(WORD in FIRST(lines)) 
/* etc. */ 

Die Idee genau zu leicht abnehmen zu sein, den Schmerz, herauszufinden, welche Sprache yacc/Bison nach tatsächlich umgesetzt hat, sind alle Heuristiken gekickt Der Rest funktioniert mehr oder weniger wie Sie angegeben haben, eine Option, die vor "leeren" Regeln warnt, es sei denn, die "leere" Regel enthält% assert (epsilon). Im Hinblick auf die Prioritäten würde ich denken, dass es eine viel höhere Priorität für Bison gibt, wenn es einen Parser erstellt hat, der die Eingabegrammatik möglicherweise nicht akzeptieren kann (z. B. können eine oder mehrere Produktionen niemals feuern). Zumindest war diese Fähigkeit nicht da, ich habe nachgesehen, aber ich habe einen ziemlich alten Bison :-). Und kann man das Problem von Produktionen mit gemeinsamen linken Präfixen, die sich durch eingebettete Aktionen unterscheiden, auf Englisch nicht erklären? Wenn es nicht viel besser geworden ist, würde ich denken, dass es noch eine Menge erklärender Verbesserungen gibt, die mehr helfen würden als eine Überprüfung auf unbeabsichtigt leere Regeln.

Es wäre interessant, einige Daten zu den häufigsten Fehlern zu sehen, mit denen die Schüler konfrontiert sind (ich hätte diesen als Kandidat nicht gewählt!). Das wäre ein interessantes Experiment: hacken Sie die Schülerkopie von Bison, damit sie jeden Lauf in eine Datenbank schickt, verwenden Sie eine Software, um sie zu bereinigen, und analysieren Sie die häufigsten Missverständnisse.

+0

Bison kann Ihnen einige Implementierungsdetails bereitstellen, z. B. die FIRSTs. Sieh dir 'bison --trace = help' an, um eine Liste möglicher Spionagespecials zu erhalten, insbesondere '--trace = sets'. Vielleicht könnte es in die '.output'-Datei gehen, anstatt nur für Betreuer verborgen zu bleiben. – akim

Verwandte Themen