Ich versuche, eine Grammatik zu erstellen, um einige von mir entwickelte Excel-ähnliche Formeln zu analysieren, wobei ein Sonderzeichen am Anfang einer Zeichenfolge eine andere Quelle kennzeichnet. $
Kann beispielsweise eine Zeichenfolge kennzeichnen, sodass " $This is text
" als Zeichenfolgeneingabe im Programm behandelt wird und &
eine Funktion kennzeichnen kann, sodass &foo()
dies als Aufruf der internen Funktion behandelt werden kann foo
.
Das Problem, mit dem ich konfrontiert bin, ist, wie man die Grammatik richtig konstruiert. Beispiel: Dies ist eine vereinfachte Version als MWE:
grammar = r'''start: instruction
?instruction: simple
| func
STARTSYMBOL: "!"|"#"|"$"|"&"|"~"
SINGLESTR: (LETTER+|DIGIT+|"_"|" ")*
simple: STARTSYMBOL [SINGLESTR] (WORDSEP SINGLESTR)*
ARGSEP: ",," // argument separator
WORDSEP: "," // word separator
CONDSEP: ";;" // condition separator
STAR: "*"
func: STARTSYMBOL SINGLESTR "(" [simple|func] (ARGSEP simple|func)* ")"
%import common.LETTER
%import common.WORD
%import common.DIGIT
%ignore ARGSEP
%ignore WORDSEP
'''
parser = lark.Lark(grammar, parser='earley')
Also, mit dieser Grammatik, Dinge wie: $This is a string
, &foo()
, &foo(#arg1)
, &foo($arg1,,#arg2)
und &foo(!w1,w2,w3,,!w4,w5,w6)
sind alle wie erwartet analysiert. Aber wenn ich meinem simple
Terminal mehr Flexibilität hinzufügen möchte , muss ich anfangen, mit der SINGLESTR
Token-Definition herumzuspielen, was nicht bequem ist.
Was habe ich versucht?
Der Teil, an dem ich nicht vorbeikommen kann, ist, dass ich func
in meiner aktuellen Situation nicht damit umgehen kann , wenn ich eine Zeichenfolge mit Klammern (die Literale sind ) haben möchte .
- Wenn ich die Klammern hinzufüge
SINGLESTR
, bekomme ichExpected STARTSYMBOL
, weil es mit derfunc
Definition verwechselt wird und es denkt, dass ein Funktionsargument übergeben werden sollte, was Sinn macht. - Wenn ich die Grammatik neu definiere, um das kaufmännische Und-Symbol nur für Funktionen zu reservieren und die Klammern hinzuzufügen
SINGLESTR
, kann ich eine Zeichenfolge mit Klammern analysieren, aber jede Funktion, die ich zu analysieren versuche, gibtExpected LPAR
.
Meine Absicht ist, dass alles, was mit a beginnt $
, als SINGLESTR
Token analysiert wird und ich dann Dinge wie analysieren kann &foo($first arg (has) parentheses,,$second arg)
.
Meine Lösung besteht derzeit darin, dass ich in meinen Zeichenfolgen "Escape" -Wörter wie LEFTPAR und RIGHTPAR verwende und Hilfsfunktionen geschrieben habe, um diese bei der Verarbeitung des Baums in Klammern zu setzen. So $This is a LEFTPARtestRIGHTPAR
produziert die richtigen Baum , und wenn ich es verarbeiten, dann wird diese übersetzt This is a (test)
.
Um eine allgemeine Frage zu formulieren: Kann ich meine Grammatik so definieren, dass einige Zeichen, die für die Grammatik spezifisch sind, in bestimmten Situationen als normale Zeichen und in anderen Fällen als speziell behandelt werden?
BEARBEITEN 1
Basierend auf einem Kommentar von habe jbndlr
ich meine Grammatik überarbeitet, um individuelle Modi basierend auf dem Startsymbol zu erstellen:
grammar = r'''start: instruction
?instruction: simple
| func
SINGLESTR: (LETTER+|DIGIT+|"_"|" ") (LETTER+|DIGIT+|"_"|" "|"("|")")*
FUNCNAME: (LETTER+) (LETTER+|DIGIT+|"_")* // no parentheses allowed in the func name
DB: "!" SINGLESTR (WORDSEP SINGLESTR)*
TEXT: "$" SINGLESTR
MD: "#" SINGLESTR
simple: TEXT|DB|MD
ARGSEP: ",," // argument separator
WORDSEP: "," // word separator
CONDSEP: ";;" // condition separator
STAR: "*"
func: "&" FUNCNAME "(" [simple|func] (ARGSEP simple|func)* ")"
%import common.LETTER
%import common.WORD
%import common.DIGIT
%ignore ARGSEP
%ignore WORDSEP
'''
Dies fällt (etwas) unter meinen zweiten Testfall. Ich kann alle simple
Arten von Zeichenfolgen (TEXT-, MD- oder DB-Token, die Klammern enthalten können) und Funktionen analysieren , die leer sind. zum Beispiel &foo()
oder &foo(&bar())
richtig analysieren. In dem Moment, in dem ich ein Argument in eine Funktion einfüge (egal welcher Typ), erhalte ich eine UnexpectedEOF Error: Expected ampersand, RPAR or ARGSEP
. Wenn ich als Proof of Concept die Klammern aus der Definition von SINGLESTR in der neuen Grammatik oben entferne, funktioniert alles so, wie es sollte, aber ich bin wieder auf dem ersten Platz.
STARTSYMBOL
), und Sie fügen Trennzeichen und Klammern hinzu, wenn dies erforderlich ist, um klar zu sein. Ich sehe hier keine Mehrdeutigkeit. SieSTARTSYMBOL
müssten Ihre Liste immer noch in einzelne Elemente aufteilen , um unterscheidbar zu sein.