Pegjs: Abkürzung für semantische Aktionen

Erstellt am 10. Sept. 2018  ·  13Kommentare  ·  Quelle: pegjs/pegjs

Es wäre schön, eine Abkürzung für semantische Aktionen hinzuzufügen.

Sagen wir, anstatt { return value } schreiben, schreiben wir zum Beispiel { extract } was im Initialisierer definiert ist.

Zum Beispiel:

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item { extract } )* _ ')' { concat }

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply { extract } )* _ ')' { toAddExpr }

Erstens werden wir dadurch in der Lage sein, Funktionen wiederzuverwenden ... auf eine schönere Weise :smile:
Zweitens wird dadurch unsere Grammatik etwas lesbarer.

Ich glaube, es ist auch nützlicher, wenn der in der Aktionskurzschrift enthaltene Ausdruck ein Mitgliedsausdruck { foo.bar.baz } anstelle des Bezeichners { foo } . Damit Grammatikschreiber ihre Funktionen innerhalb eines Objekts oder sogar eines Moduls organisieren können.

discussion feature

Hilfreichster Kommentar

Eigentlich habe ich mir überlegt, diese Änderungen könnten einfach funktionieren:

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Auf diese Weise müssen immer noch einige Dinge wie die primären Ausdrücke von ECMAScript (Zahlen, Boolesche Werte, Arrays usw.) integriert werden, die als Argumente verwendet werden. Sie müssen also sorgfältig herausfinden, was hinzugefügt werden soll.


Balancierende Klammern und Klammern

Dies wird nicht behoben, bis ein richtiger JavaScript-Parser in den PEG.js-Parser integriert ist, aber um ehrlich zu sein, zögere ich etwas, da es einige Plugin-Projekte gibt, die Parser in anderen Sprachen (C, PHP, TypeScript) generieren , etc), und ich arbeite auch an einer Computersprache, in der ich hoffe, eines Tages Parser generieren zu können.


Neben _PEG.js v0.12_ werde ich an OpenPEG arbeiten , das ein NPM-Paket

Alle 13 Kommentare

Interessante Idee, aber ich persönlich glaube nicht, dass dies ein klarerer Weg wäre, da nicht offensichtlich ist, welche Argumente an die Funktion übergeben werden. Wenn Sie auch einen "benutzerdefinierten" Parameter übergeben müssen, müssen Sie diese mit normalen Funktionsaufrufen mischen, damit es nicht so sauber aussieht wie in den einfacheren Fällen.

Jemand in #235 schlug die Syntax => für Pfeilfunktionen vor, die meiner Meinung nach recht sauber und prägnant war.

  = '(' expr:some_expression ')' => expr
  ;

Ich tendiere dazu, eine der folgenden Abkürzungen für die Syntax zu wählen:

  • => expr; _(benötigt Syntaxunterstützung)_
  • { => expr } _(jetzt verwendbar, muss aber ausgepackt werden)_
  • { > expr } _(benötigt Syntaxunterstützung)_

Habe mich noch nicht entschieden, also steht es zur Diskussion.

Was das OP will, ist es am besten, ein Plugin zu implementieren (nach oder bevor die Abkürzungssyntax festgelegt ist), das Acorn oder @babel/parser verwendet, um den Bezeichner oder den Mitgliedsausdruck zu entpacken, ihn in einen Aufrufausdruck umzuwandeln, während Sie das hinzufügen Labels als Argumente und geben den generierten Code zurück.

=> expr;

Meiner Meinung nach am besten.

{ => expr }

Konflikte mit Javascript-Syntax IMO. Da es sich in { } , würden Sie erwarten, dass es sich um eine vollständige Pfeilfunktion handelt ( () => ).

{ > expr}

Ein bisschen orthogonal zu jeder anderen Syntax in PegJS oder Javascript, liest IMO nicht sofort "dies gibt einen Wert zurück", eine Abkürzung - hauptsächlich, weil es in geschweiften Klammern steht, denke ich. Gleiches Argument wie {=> expr} , Sie erwarten, dass Javascript drin ist.


Darüber hinaus ist das Hinzufügen von Nicht-JS-Syntax in {} ein Problem für Syntax-Highlighter, Linters usw. Ich empfehle dagegen.

Wenn ich noch eine andere Option vorschlagen darf, vielleicht > allein (nicht innerhalb eines Prädikatblocks). Das hilft, die Dinge ausgerichtet zu halten, wenn Sie Regeln vertikal verteilen:

    = foo:bar qux:(' '+ @qix)+
    > {foo, qux}
    ;

sowie Inline

some_rule = foo:bar qux:(' '+ @qix)+ > {foo, qux};

Warum wird das Semikolon für '=>' benötigt? Ich möchte beispielsweise einen Wert in verschachteltem Code zurückgeben, anstatt buildList() zu verwenden:

  = "(" _ head:Expression _ tail:("," _ expr:Expression => expr)* ")" {
      return [head, ...tail]
    }

Ich finde das sauberer, als einen magischen Index (unten) zu verwenden. Eine weitere Option ist die Möglichkeit, auf verschachtelte Labels zu verweisen. zB ("," _ tail:Expression)* ")"

  = "(" _ head:Expression _ tail:("," _ Expression)* ")" {
      return buildList(head, tail, 2)
    }

Ich habe mir parser.pegjs angesehen und sehe in Zeile 434 CodeBlock. Was müsste man tun, um es auszuprobieren? Der Regelcode liest einfach SourceCharacter, was einfach '.' ist.

CodeBlock "code block"
  = "=>" __ <strong i="13">@Code</strong> // this?
  / "{" <strong i="14">@Code</strong> "}"

@mikeaustin Ja, das ist ungefähr richtig, aber es gibt keine Möglichkeit zu wissen, wo diese Sequenz dann enden soll, also wird alles nach => verbraucht

Vielleicht könnte "Code" etwas intelligenter sein, Klammern und Klammern ausbalancieren und mit LineTerminator umgehen? Es müsste nicht über vollständiges JavaScript Bescheid wissen, aber das kann schwieriger sein, als es klingt.

Eigentlich habe ich mir überlegt, diese Änderungen könnten einfach funktionieren:

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Auf diese Weise müssen immer noch einige Dinge wie die primären Ausdrücke von ECMAScript (Zahlen, Boolesche Werte, Arrays usw.) integriert werden, die als Argumente verwendet werden. Sie müssen also sorgfältig herausfinden, was hinzugefügt werden soll.


Balancierende Klammern und Klammern

Dies wird nicht behoben, bis ein richtiger JavaScript-Parser in den PEG.js-Parser integriert ist, aber um ehrlich zu sein, zögere ich etwas, da es einige Plugin-Projekte gibt, die Parser in anderen Sprachen (C, PHP, TypeScript) generieren , etc), und ich arbeite auch an einer Computersprache, in der ich hoffe, eines Tages Parser generieren zu können.


Neben _PEG.js v0.12_ werde ich an OpenPEG arbeiten , das ein NPM-Paket

FWIW, ich habe angefangen, dafür Vorlagenliterale zu verwenden. Es hilft mir auch bei der Syntaxhervorhebung von JS durch meinen Texteditor...

exports = module.exports = functionBodies`${grammarScript}
...
objectText =
    head:word
    rest:(_txt_ word)*
    ${f=>{
        return new Txt(rest.reduce((a,b)=>([...a,...b]),[head]))
        }}
word = ch:(wordCharacter/escapedCharacter)+ ${chJoin}
...
`
function functionBodies(glue, ...fns){
    return glue.map( (str,i) => str + (fns[i]||'').toString().replace(/^[^{]*/,'').replace(/[^}]*$/, '') ).join('')
    }

function chJoin(ch){return ch.join('')}

Wie wäre es mit dem vorgeschlagenen Pipe-Operator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator)? Weil Sie im Grunde genommen darum bitten, die Daten weiterzuleiten?

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item |> extract )* _ ')' |> concat

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply |> extract  )* _ ')' |> toAddExpr

Nichts davon sollte passieren. Es sollte keine kurze Syntax geben.

Nichts davon ist notwendig, wenn wir Pfeile normal parsen, anstatt zu versuchen, sie seitwärts zu verschieben.

Obwohl dies eine nette Idee ist, führt sie im Vergleich zu JavaScript zu umfangreichen grammatikalischen Mehrdeutigkeiten. Jeder, der JS geparst hat und sich daran erinnert, was für ein Debakel with war, weiß, dass dies im Grunde genommen einen Parser umbringen wird.

Anstatt zu versuchen, ausgefallene neue Sachen zu erstellen, sollten wir einfach Javascript unterstützen. Pfeilfunktionen sind älter als ES6 und ES6 ist von 2015. Dies wurde vor sechs Jahren gelöst. Hier darf keine Erfindung passieren.

Der Pipe-Operator ist stark fehlerhaft und wird es wahrscheinlich nicht wirklich in Javascript schaffen, und sowohl die Sprache, aus der er ursprünglich stammt (F#) als auch die Sprache, die ihn populär gemacht hat (Elixir), weichen davon ab. Außerdem ist dies in keiner Weise ein Rohr.

Der Grund, warum PEG so erfolgreich war, war, dass es minimal war und nah an der Sprache blieb, was es ermöglichte, schnell, klein und vorhersehbar zu sein.

Pfeilfunktionen sind älter als ES6 und ES6 ist von 2015. Dies wurde vor sechs Jahren gelöst. Hier darf keine Erfindung passieren.

Äh. Das ist mir neu. Möchten Sie expandieren?

Der Grund, warum PEG so erfolgreich war, war, dass es minimal war und nah an der Sprache blieb, was es ermöglichte, schnell, klein und vorhersehbar zu sein.

Der Grund, warum PEG (als Konzept, nicht diese Bibliothek) erfolgreich ist, liegt in seiner Fähigkeit, komplexe Grammatiken (rekursiv usw.) auf einfache Weise darzustellen. Packrat wurde nicht mit dieser Bibliothek erfunden; es ist keine Syntax. Es ist ein Algorithmus.

Pfeilfunktionen sind älter als ES6 und ES6 ist von 2015. Dies wurde vor sechs Jahren gelöst. Hier darf keine Erfindung passieren.

Äh. Das ist mir neu. Möchten Sie expandieren?

Ich weiß nicht wirklich, was Sie fragen.

Pfeilfunktionen sind älter als ES6. Dies war der zweitgrößte Kampf in ES6, was ES4 entgleist und ES5+ entgleist. Jeder hatte zu diesem Zeitpunkt seit Mitte der 90er Jahre danach gefragt, weil sie tatsächlich schon in E4X existierten und weggenommen wurden, weil Google und Apple Hixie über den Haufen geworfen hatten, dass Microsoft jemals etwas erfinden würde.

Sie kennen E4X jetzt als React und denken, dass Facebook es erfunden hat. Facebook glaubt, Hyperscript abgezockt zu haben. Dem Hyperscript-Typ ist klar, dass er nur eine nützliche Sache aus dem alten IE neu implementiert hat.

Sie würden komplett aus ES6 weggelassen werden, genau wie Template-Strings, aber dann kam Coffeescript und gab der JS-Community beides, und dann schrie die JS-Community, bis die ECMA-Leute sich rührten. Hat nur 18 Monate gedauert

Pfeilfunktionen erledigen hier alles, was passieren muss. Sie scheinen sogar die Person zu sein, die sie 2018 in diesem Thread angesprochen hat, was Ihre Meinungsverschiedenheit ziemlich überraschend macht; Ich habe versucht, dich zu unterstützen.

Noch wichtiger ist mir, wenn es mit einer Pfeilfunktion gemacht wird, wurde nichts hinzugefügt.

Die Unterschiede von Peg zu JS sind absolut minimal. Wenn Sie dies nur durch ES6-Zeug unterstützen, bedeutet dies, dass sich die Liste nicht ändert.

Das ist extrem wertvoll.


Der Grund, warum PEG (als Konzept, nicht diese Bibliothek) erfolgreich ist, liegt in seiner Fähigkeit, komplexe Grammatiken (rekursiv usw.) auf einfache Weise darzustellen.

Ich stimme nicht zu. Viele Parser machen das viel besser und sind nicht einmal ein bisschen beliebt, selbst bei den Leuten, die sie kennen (wie Earley).

Die traditionelle Erklärung ist eine Kombination aus Fehlermeldungsqualität und Geschwindigkeit, aber auch dem stimme ich nicht zu, da viele Parser schneller bessere Fehlermeldungen haben (wiederum wie Earley) und nicht einmal ein bisschen beliebt sind, selbst bei den Leuten wer kennt sie

Beachten Sie auch, dass PEG drei schwerwiegende Komplexitätsgrenzen hat.

Erstens muss alles, was Sie durch eine Peg-Grammatik übertragen möchten, einen kombinatorischen Ausdruck haben, der den Cache und den Auswertungsdurchsatz des lokalen Computers nicht überfordert (in Beispiel #623)

Zweitens sind viele gängige Jobs, wie das Parsen von BNF, in Peg häufig brutal schwierig (am Beispiel #489).

Drittens ist es erwähnenswert, dass jede andere JS-PEG-Bibliothek, sogar wesentlich leistungsfähigere, versagt hat. Ich habe versucht, wegzuschalten, und bin oft zurückgekommen. Insbesondere habe ich mehrmals versucht, zu canopy zu wechseln, weil ich damit zusätzlich auf c , ruby und python abzielen kann zu javascript

Zugegeben, ich kann nur für die zwei Dutzend Leute sprechen, die ich kenne, die es benutzen. Und das kann ich, weil ich vor ein paar Tagen nachgefragt habe, als mir klar wurde, dass der neue Nicht-Maintainer die Software wegwirft und durch etwas ersetzt, das er selbst erstellt hat, nachdem jahrelang keine Änderungen veröffentlicht wurden

Aber jeder einzelne von ihnen sagte zu mir, dass sie entweder einen Parser brauchen, der nicht viel nativen konzeptionellen Overhead hat, oder dass sie etwas Schnelles und Kleines brauchen, dessen Verhalten zuverlässig ist

Unreleased 0.11 verhält sich in Node und Chrome sinnvoll anders, und Node besteht aus Chrome. Versuchen Sie, einige Eigenschaftstests dagegen zu schreiben. Es ist ehrlich gesagt irgendwie erschreckend.

.

Packrat wurde nicht mit dieser Bibliothek erfunden; es ist keine Syntax. Es ist ein Algorithmus.

Ich habe nichts von Packrat gesagt, Freund. Ich bin mir nicht sicher, was Sie korrigieren möchten.

Packrat-Parsing ist jedoch kein Algorithmus, aus dem gleichen Grund wie Sortieren kein Algorithmus. Packrat-Parsing ist eine Aufgabe, und es gibt viele Möglichkeiten, dies zu tun.

Tatsächlich lassen dich die meisten Haskell-Intro-Bücher drei oder vier verschiedene Packrat-Parser ausführen, weil sie eine großartige Möglichkeit sind, sich wirklich an den Leistungsproblemen von Haskells Herangehensweise an Monaden zu hängen, und sie wollen dir zeigen, wie sich die Herangehensweise an das Schreiben ändern kann packrats (d. h. das Ändern des Algorithmus) führt zu besseren Ergebnissen.

.

Bitte überdenken Sie das Daumen nach unten. Diese Bibliothek ist seit drei Jahren tot, und ich möchte sie jetzt wiederbeleben.

Ein Grund dafür, dass die Bibliothek tot ist, ist, dass die Leute immer wieder versuchen, neue Funktionen zu erfinden, anstatt einfache Wartungen durchzuführen, wie das Hinzufügen der Modulfunktion es() , die seit zwei Jahren in der Entwicklung steckt

Ich muss meine PEG-Parser manuell ändern, indem ich Linien schneide und handgeschriebenes Javascript an das Ende hefte

Die Sternenaugen sollten sich für eine Weile schließen und einige praktische fettige Ellbogen sollten beginnen. PEG ist die einzige große NPM-Bibliothek, die ich je gesehen habe, mit rückläufiger Nutzung. Da mir kein vernünftiger Ersatz bekannt ist, ist das für mich bizarr und verwirrend.

image

Ich habe Bugfixes, die ich jetzt beitragen möchte, aber ich kann nicht, weil

  1. 0.10 wurde nicht veröffentlicht, seit dmajda gegangen ist,
  2. 0.11 ist drei Jahre alt, wurde noch nie veröffentlicht und es wurde vor einem Monat angekündigt, dass es nie veröffentlicht wird, und
  3. Der Ersatz, 0.12 , ist überhaupt kein Peg, sondern etwas, das der andere von Grund auf in einer anderen Programmiersprache geschrieben hat, und keiner von uns kann es sehen

Ich weiß, es ist unhöflich, aber wir müssen uns damit abfinden, dass diese Bibliothek getötet wird

Es ist an der Zeit, uns der Tatsache zu stellen, dass wir einen normalen Entwicklungsprozess akzeptieren müssen, wenn diese Bibliothek jemals wieder aktualisiert wird. Es ist 2020. Wir haben seit 2017 nichts mehr gesehen.

Nein, der Entwicklungszweig zählt nicht. Und der neue Betreuer wird eine Menge Probleme neu aufmachen müssen, weil 0.11 nicht von ausreichender Qualität ist, und es ist viel weniger Arbeit, mit 10 anzufangen, als 11 reparieren

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

dmajda picture dmajda  ·  15Kommentare

mreinstein picture mreinstein  ·  12Kommentare

richb-hanover picture richb-hanover  ·  7Kommentare

StoneCypher picture StoneCypher  ·  8Kommentare

emmenko picture emmenko  ·  15Kommentare