Pegjs: Möglichkeit, die Anzahl der Wiederholungen anzugeben (wie in regulären Ausdrücken)

Erstellt am 11. Aug. 2011  ·  22Kommentare  ·  Quelle: pegjs/pegjs

Es wäre hilfreich, wenn die PEG.js-Grammatik die Verwendung von so etwas wie Bereichsausdrücken von POSIX-Basisregulären Ausdrücken erlauben würde. Z.B:

  • "a"\{1,7\}

entspricht a , aa , ..., aaaaaaa

  • "a"\{0,1\}

entspricht der leeren Zeichenfolge und a

  • "a"\{,6\}

stimmt mit einer Zeichenfolge mit bis zu (einschließlich) sechs a überein

  • "a"\{6,\}

stimmt mit einer Zeichenfolge von sechs oder mehr a überein

  • "a"\{3\}

entspricht nur aaa , was "a"\{3,3\} entspricht

feature

Hilfreichster Kommentar

Ich würde mich auch über Wiederholungszahlen freuen. Aber ich würde eine etwas andere Syntax vorschlagen. Pegasus ist fast identisch mit Pegjs, nur für C#. Siehe hier: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

Und sie haben diese Funktion so implementiert: d<3> e<2,> f<1,5>

Alle 22 Kommentare

Ich werde diese Funktion nicht implementieren.

Der Hauptgrund ist, dass in der PEG.js-Grammatik kein Platz für die {m,n} -Syntax ist – Klammern werden bereits für Aktionen verwendet, und ich möchte keine umgekehrten Schrägstriche verwenden, wie Sie vorschlagen (sie sind hässlich und nicht kompatibel mit Perl Regexps, die jetzt am häufigsten verwendet werden und auch Quelle anderer PEG.js-Syntax) oder anderer Trennzeichen (das wäre verwirrend).

Nach meiner Erfahrung tritt diese Art der begrenzten Wiederholung hauptsächlich bei den "lexikalischen" Teilen der Grammatik auf (Regeln wie color = "#" hexdigit hexdigit hexdigit hexdigit hexdigit hexdigit ) und nicht so oft. Ich denke, es ist in Ordnung, dort nur Sequenzen von Ausdrücken und vorhandene Wiederholungsoperatoren ( * , + , ? ) zu verwenden.

Ich habe es mir nochmal überlegt und eröffne das Thema erneut. Es scheint, dass die Möglichkeit, eine beliebige Anzahl von Wiederholungen festzulegen, von Benutzern sehr gewünscht wird.

Ich möchte eine regexp-ähnliche {m,n} -Syntax vermeiden, da { und } bereits für Aktionen verwendet werden und ihre Wiederverwendung zu Mehrdeutigkeiten führen würde. Ich denke derzeit an so etwas:

"foo" @ 1..10   // repeat 1 to 10 times
"foo" @ 1..     // repeat at least once
"foo" @ ..10    // repeat at most 10 times

Die größte Frage ist, was die Trennzeichen sein sollten und wie man Bereiche auszeichnet.

Was das Trennzeichen betrifft, so scheint mir @ nett. Ich habe % und # nachgedacht, aber in meinen Augen ist das erste bereits mit String-Interpolation (z. B. in Python) und das zweite mit Kommentaren (in verschiedenen Sprachen) verbunden. Ich denke auch darüber nach, das Trennzeichen ganz zu überspringen:

"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

Was das Bereichs-Markup betrifft, habe ich mich von Ruby inspirieren lassen. Ich habe auch an - gedacht, aber es sieht zu sehr nach einem Minuszeichen aus. Andererseits sieht Python-ähnliches : für mich auch gut aus.

Bei halboffenen Bereichen bin ich mir nicht sicher. Vielleicht wäre es besser, sie mit + und - wie folgt zu markieren:

"foo" @ 1+    // repeat at least once
"foo" @ 10-   // repeat at most 10 times

Irgendwelche Ideen oder Kommentare?

Wirklich cool, dass Sie planen, diese Funktion zu unterstützen!

Ich mag Ihren (Standard-)Vorschlag:
"foo" @ 1..10 // 1 bis 10 Mal wiederholen
"foo" @ 1.. // Mindestens einmal wiederholen
"foo" @ ..10 // höchstens 10 mal wiederholen

Ich mag die +/- Syntax für halboffene Bereiche nicht, die Doppelpunkt-Syntax ist meiner Meinung nach viel intuitiver und lesbarer.

Das einzige, worüber ich nachgedacht habe, war die Verwendung von "#" vs. "@", da IMO "#" natürlich Zahlen/Zählen impliziert, während "@" natürlich eine Referenz impliziert, sodass "#" möglicherweise etwas intuitiver und lesbarer ist (und vielleicht könnten Sie das "@" in Zukunft für etwas verwenden?). Aber das ist wirklich ein kleines Problem, und ich wäre mit der "@" -Syntax zufrieden.

Prost!

Nur ein kurzer Kommentar: Ich denke, dass @ und % eine bessere Wahl sind als # , weil Syntax-Highlighter, die die PEG.js-Grammatik nicht unterstützen, insbesondere solche, die versuchen zu erraten die Syntax (z. B. der Code-Highlighter von Stack Overflow) wird wahrscheinlich # als Beginn eines Kommentars interpretieren, was dazu führt, dass er – ärgerlicherweise – von diesem Punkt an bis EOL in der „Kommentarfarbe“ angezeigt wird. Dies ist natürlich keine Präferenz, die auf Logik und Argumentation basiert, sondern auf Pragmatismus.

Wie wäre es mit einem Sonderfall für {num, num} gleichermaßen? Was Wiederholung bedeutet, da { , num} und { num, } kein gültiger js-Code sind und {num, num} und { num } sinnlos sind.

Sie sind wahrscheinlich nicht aussagekräftig, selbst wenn die Handlung in anderen Sprachen erfolgt.

Ich mag diese Varianten unter den vorgeschlagenen (aber das ist natürlich Ihre Wahl, da Sie der Autor sind :)):

// why we need separator, anyway? for me it looks very cool and simple to understand
"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

oder

"foo"@1..10   // repeat 1 to 10 times
"foo"@1..     // repeat at least once
"foo"@..10    // repeat at most 10 times

aber das zweite ist weniger vorzuziehen

die x..y / ..y / x.. Idee sieht sehr cool aus, da .. dank ihr als konsistenter Operator aussieht.

+/- sind für mich nicht ok, weil sie verwirren und zu den zusätzlichen Operatoren über .. werden (und + wird bereits verwendet)

Denke nochmal drüber nach. Werden diese funktionieren?

'foo'<1,5>
'foo'< ,3>
'foo'<2, >

da < und > derzeit von der Grammatik nicht verwendet werden

:+1: von mir sieht das gut aus.

natürlich ist <,3> äquivalent zu <0,3> , also können wir genauso gut nur die Mindestzahl benötigen. Dies wäre deckungsgleich mit dem, was ECMA für reguläre JavaScript-Ausdrücke getan hat.

Ich mag die <,> . Aber ich würde auch vorschlagen, dass <3> dasselbe ist wie <3,3> .

Ich stimme zu, die <> -Syntax sollte so weit wie möglich direkt auf das Verhalten von {} in RegExp abgebildet werden.

Wenn ich mich nicht irre, müssen keine Trennzeichen hinzugefügt werden, es sei denn, Sie möchten Variablennamen in den Bereichen zulassen.

foo 1,2 fighter
bar ,3 tender
baz 4, lurhmann
qux 5 quux

sind alle eindeutig.

@pygy , das Problem, kein Trennzeichen zu verwenden, besteht darin, dass es möglicherweise die Entwicklung der Syntax der Sprache erstickt.

Wenn wir zum Beispiel das Komma später für etwas anderes verwenden wollten, hätten wir jetzt überall Probleme mit Syntaxkollisionen. Wenn Sie es auf <> Klammern beschränken, wird die Oberfläche von Kommas und Zahlen erheblich reduziert.

Außerdem sind die Leute sowieso daran gewöhnt, den {1,6} -Stil in RegExps zu verwenden.

Ich halte nichts von der Syntax, aber ich möchte diese Funktion, und es wäre großartig, wenn ein Ausdruck als Bereichswert verwendet werden könnte.

Mein Anwendungsfall: Analysieren von Literalen in IMAP-Serverantworten, die wie {42}\r\n... aussehen, wobei 42 die Anzahl der Zeichen nach dem Zeilenumbruch ist, die eine Zeichenfolge darstellen (hier als Auslassungszeichen dargestellt). Da es für ein IMAP-Literal kein Endtrennzeichen gibt, ist die Zeichenzählung die einzige Möglichkeit, diese Antwort zu analysieren.

Wie sieht es mit Variablen in Einschränkungen aus? Dies ist sehr nützlich für Nachrichten mit Header, die ihre Länge enthalten. Zum Beispiel Grammatik

  = len:number message:.<len,len> .* {return message;}
number
  = n:[0-9] {return parseInt(n);}

parsen muss

4[__] -> ['[', '_', '_', ']']
4[___] -> ['[', '_', '_', '_']
4[_] -> Error: expected 4 chars, got 3

Dies ist für viele Protokolle nützlich.

Kann diese Syntax verwenden:
expression |min,max| , dann können spitze Klammern für Vorlagenregeln verwendet werden.

Überlegen Sie noch, dies umzusetzen?
Was ist mit etwas, das den ABNF- Bereichen ähnelt?

exp *     // 0 or more times
exp 1*    // at least once
exp *10   // up to 10 times
exp 1*10  // 1 to 10 times

Hallo. Ich muss ein komplexes Dateiformat analysieren. Es ist halb binär, halb ASCII.

Hier eine vereinfachte Version des Problems:

KK4TesRandom oder KK10TestATestBRandom

Die Logik:

<StringIndicator><StringLength><String><otherStuff>

Das KK ist der Indikator zum Markieren einer Zeichenkette. Die folgenden Ziffern (hier 4 und 10 ) geben die Länge des Strings an. Dann der String selbst (hier Test und TestATestB ). Der String wird durch kein vorhersagbares Muster beendet. Ich muss grundsätzlich die Längenangabe verwenden. Ich würde sagen, dass dies ein gängiges Muster in binären Dateiformaten ist, aber ist es möglich, mit der aktuellen Grammatik zu analysieren?

Danke.

Ich implementiere so etwas in meinem Zweig ranges-dynamic-boundary . Grammatik wird so aussehen:

start = len:nx data:.|len| { return data; };
nx = n:$[0-9]+ { return parseInt(n, 10); };

@Mingun wow! Das funktioniert wie ein Zauber! Vielen Dank für deine Implementierung und das kurze Beispiel. Ich habe ein paar Tests gemacht und es funktioniert super. Ich hoffe, dass Ihre Pull-Anfrage vom Master akzeptiert wird.

Ich würde mich auch über Wiederholungszahlen freuen. Aber ich würde eine etwas andere Syntax vorschlagen. Pegasus ist fast identisch mit Pegjs, nur für C#. Siehe hier: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

Und sie haben diese Funktion so implementiert: d<3> e<2,> f<1,5>

Was sind die Workarounds der Leute dafür? Ich steige gerade in PEGjs ein, also versuche ich vielleicht, eine Schraube mit einem Hammer zu drehen, aber ich versuche nur, zwischen 1 und 6 Ziffern abzugleichen :)

Ich verwende meine eigene Implementierung (siehe Nr. 267 für Syntax, die endgültige Lösung unterstützt Zahlen, Variablen und Codeblöcke als Grenzen) und ich werde bald PR für Peggy vorbereiten (Umbenennung der PEG.js-Verzweigung, die beibehalten wird).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen