Pegjs: Rückgabe des Übereinstimmungsergebnisses eines bestimmten Ausdrucks in einer Regel ohne Aktion zulassen

Erstellt am 23. Mai 2016  ·  10Kommentare  ·  Quelle: pegjs/pegjs

Es ist sehr üblich, einen Wert von einem der Nicht-Terminals in einer Regel oder innerhalb einer eingeklammerten Unterregel zurückzugeben. Zum Beispiel:

varDecl = type:type id:ID init:( EQ e:expr {return e} )?
                { return scopedAST('VARDECL', {type, id, init}) }

In diesem Fall brauchte ich das expr mit der Bezeichnung e innerhalb der init Klammerebene für eine optionale Phrase in der Sprache. Ich brauchte das "Noise-Wort" EQ als Teil des zurückgegebenen Wertes.

Wenn die PEGjs-Sprache ein Symbol hätte, das verwendet werden könnte, um Terminals wie das expr oben zu markieren, damit sie und nur sie der Wert sind, der von einer Grammatikregel oder Unterregel zurückgegeben wird, wäre dieser Fall einfacher.

Um mein obiges Beispiel umzuschreiben:

varDecl = type:type id:ID init:( EQ ^expr )?
                { return scopedAST('VARDECL', {type, id, init}) }

Beachten Sie die Verwendung von ^ , um den expr Wert innerhalb der init optionalen Phrasen-Unterregel in Klammern zu markieren, um anzugeben, was an init gebunden ist. Dies vereinfacht viele Situationen sowohl mit als auch ohne die in diesem Beispiel gezeigte Unterregel in Klammern.

Vielen Dank, dass Sie ein so wunderbar einfaches, elegantes und leistungsstarkes Tool entwickelt haben. Ich liebe PEGjs! :Lächeln:

feature

Alle 10 Kommentare

Liebe diese Idee! ^ ist auch sehr intuitiv.

Dies könnte auch bei nicht verschachtelten Regeln funktionieren:

WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = WhiteSpace? ^Identifier WhiteSpace?

Sehr lesenswert! Vermutlich würde auch die Verwendung mehrerer ^ funktionieren, so dass:

a = ^b  c  ^d  e

Würde [b, d] ? Scheint sinnvoll zu sein.

Ebenso scheint es sinnvoll zu sein, dass die ^ Regeln ignoriert werden, wenn sie mit benannten Captures gemischt werden

x = a ^b foo:c { return foo; }

Würde nur c zurückkehren.

Oh, diese Multiple-Idee ist ausgezeichnet. Das Mischen mit benannten Captures sollte sein
ein Fehler.

Am Di, 5. Juli 2016, 01:07 Uhr Graham Wakefield [email protected]
schrieb:

Sehr lesenswert! Vermutlich würde die Verwendung von mehreren ^ auch funktionieren, so dass:

a = ^bc ^de

Würde [b, d] zurückgeben? Scheint sinnvoll zu sein.

Ebenso scheint es sinnvoll zu sein, dass die ^
Regeln werden ignoriert:

x = a ^b foo:c { return foo; }


Sie erhalten dies, weil Sie den Thread verfasst haben.

Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/pegjs/pegjs/issues/427#issuecomment -230413015 oder stumm
der Faden
https://github.com/notifications/unsubscribe/ABC26k8v0DIzuWUlkoDZGm2ep10Y5bcMks5qShDAgaJpZM4IkuA9
.

Ich stimme voll und ganz zu, dass das beschriebene Muster recht häufig ist. Es ist sinnvoll, eine Möglichkeit zu haben, dies ohne eine Aktion auszudrücken.

Was ich mir bei der vorgeschlagenen Lösung (der ^ Operator) nicht so sicher bin. Die Verwendung eines Sonderzeichens, dessen Bedeutung nicht sofort ersichtlich ist, ist immer problematisch und erhöht die Lernkurve. Es ist auch möglich, dass der Charakter für einen anderen Zweck besser verwendet wird. Zu guter Letzt gefällt mir die Idee nicht, Dinge, die das Parsen nicht direkt beeinflussen, in Ausdrücke zu packen. Man kann argumentieren, dass es bereits eine Instanz davon gibt – den $ -Operator – und ich stimme zu. Aber ich bin mir nicht sicher, ob das Hinzufügen von $ kein (kleiner) Fehler war. Wenn ja, möchte ich es vermeiden, es noch einmal zu machen.

Ich werde nach 1.0.0 genauer darüber nachdenken.

Noch ein Denkanstoß: Da ^ und gekennzeichnete Ausdrücke irgendwie kollidieren ( @grrrwaaa schlagen vor, die ^ ignorieren), wie wäre es, anstatt das Ergebnis zu markieren, könnte man zum Beispiel die _ignorierten_ Ausdrücke markieren (Syntaxvorschlag!) durch Angabe eines leeren Labels:

WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = :WhiteSpace? Identifier :WhiteSpace?

Dort gibt es keine neue Syntax (wir haben bereits : ), nur eine kleine Erweiterung der Semantik:

  • leere Labels zulassen (diese "anonymen" Ausdrücke nennen?)
  • wenn nur eine nicht-anonyme Erfassung vorhanden ist, kein Array von Ausdrucksübereinstimmungen generieren, sondern die einzige Übereinstimmung zurückgeben

In diesem Fall markiert konsistentere Ausdrücke mit leeren "Labels" die Ausdrücke, die als Ergebnis zurückgegeben werden müssen. Übrigens, um die bestehende Semantik nicht zu brechen: Das Label existiert, aber es ist unbenannt; Da Labels für den Zugriff auf das Ergebnis eingeführt werden, ist es ziemlich logisch, dass unbenannte Labels automatisch zu Ergebnis werden. Das gleichzeitige Vorhandensein von automatischen und konkreten Etiketten ist verboten. Wenn nur ein automatisches Label vorhanden ist, muss das einzelne Ergebnis, aber kein Array mit einem Element zurückgegeben werden, da ein solches Verhalten stärker gefordert ist.

@Mingun

Warum nicht einfach jedes Etikett zurücksenden?
start = "{" :expr "}" // return expr
start = "{" label:expr "}" // return label
Ich denke, es macht Sinn, wenn man etwas "kennzeichnet", dann möchte man etwas damit machen (zB zurückgeben).

Andererseits, warum sollten Regeln wie start = ex:expr :expr einen Fehler verursachen?
Vielleicht sollte es etwas Ähnliches wie die Argumentvariable der Javascript-Funktionen tun? Zum Beispiel sollte start = ex:expr :expr [ex, expr] . Wenn Sie eine Aktion haben, sollten die Variablen & arguments ( start = ex:expr :expr { return [ex, arguments[0], ex] } )

@alanmimms Ich mag diese Idee. Wir müssen keinen Namen (eine Variable/ein Label) erstellen, nur um einen einfachen Wert zurückzugeben.
Ich denke, ein unbenanntes Label ( :expr ) wäre besser als ^expr

Warum nicht einfach jedes Etikett zurücksenden?

@nedzadarek, denn wenn Sie einem Ausdruck einen Namen geben, ist es wahrscheinlicher, dass Sie ihn nicht in einem nicht trivialen Ausdruck verwenden. Zumindest ist der Name wichtig für dich, sonst würdest du ihn nicht nennen, wirklich? Außerdem ist das Mischen von benannten und unbenannten Labels wahrscheinlicher ein Fehler als eine bewusste Aktion, daher ist es sicherer, wenn es verboten wird. Wenn Sie einen Namen angeben, warum nicht einen anderen angeben?

Leider ist es notwendig zu erkennen, dass automatische Labels in diesem Look in dem, was sie von @opatut anbieten , nicht implementiert werden können, da dies Mehrdeutigkeiten in der Grammatik erzeugt. Das elementare Beispiel:

start = a :b;// `a` - it is rule reference or label?
a = .;
b = .;

Zu diesem Zweck müssen Sie ein anderes Zeichen auswählen. Momentan stehen zur Auswahl: ~ , (backslash) , @ , # , % , ^ , - , | , \ und , .


Eine andere Lösung -- führen Sie einige Pseudo-Aktionen ein -- eine Abkürzung zum Erstellen einfacher Funktionen für die Rückgabe, zum Beispiel {=>[]} kann bedeuten, _"die markierten Ergebnisse aus der Sequenz zu sammeln und sie in das Array zurückzugeben"_ , und {=>{}} -- dasselbe, aber um ein Objekt zurückzugeben, wobei die Schlüssel den Namen der Labels entsprechen. Die Implementierung dieses Verhaltens erfordert jedoch keine Erweiterung der Grammatik und kann durchaus durch Plug-Ins realisiert werden. Ich würde sogar sagen, dass es vorzuziehen ist, eine solche Implementierung durch Plug-Ins zu haben:

start1 = a:'a' b c d:. {=>[]};// returns ['a', <d value>]
start2 = a:'a' b c d:. {=>{}};// returns { a: 'a', d: <d value> }

@Mingun

denn wenn Sie einem Ausdruck einen Namen geben, ist es wahrscheinlicher, dass Sie ihn nicht in einem nicht trivialen Ausdruck verwenden. Zumindest ist der Name wichtig für dich, sonst würdest du ihn nicht nennen, wirklich?

Ja, der Name ist wichtig => Ich möchte ihn verwenden => Ich möchte ihn zurückgeben.
Was ist das Problem mit nicht-trivialen Ausdrücken?

Leider ist es notwendig zu erkennen, dass automatische Labels in diesem Look in dem, was sie von @opatut anbieten , nicht implementiert werden können, da dies Mehrdeutigkeiten in der Grammatik erzeugt. Das elementare Beispiel:

Jawohl.
Ich denke, ::expression ist auch verwirrend? @dmajda

Geschlossen als Duplikat von #235

Bearbeiten: Hinweis zum Kommentar von OP zu Nr. 235 hinzugefügt, der auf dieses Problem verweist

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

StoneCypher picture StoneCypher  ·  6Kommentare

StoneCypher picture StoneCypher  ·  8Kommentare

futagoza picture futagoza  ·  6Kommentare

mattkanwisher picture mattkanwisher  ·  5Kommentare

marek-baranowski picture marek-baranowski  ·  6Kommentare