joetjen.net
EN DE
Grammatiksprache

Notausgänge

Manche lexikalischen Entscheidungen hängen von mehr ab als der längsten Übereinstimmung, und manche Sprachen ändern ihre Syntax unterwegs. Drei Pragmas decken diese Fälle ab, und jedes benennt genau, was es berührt.

Ichor 0.3

Schlüsselwörter

@keywords benennt ein Token nach dem Lexen um, wenn sein Text in einer Tabelle steht. Die neuen Namen brauchen keine eigene Deklaration:

WORD := [a-zA-Z_][a-zA-Z0-9_]*
@keywords WORD { "if" -> KEYWORD_IF, "return" -> KEYWORD_RETURN }

Jedes WORD, das if lautet, erreicht den Parser als KEYWORD_IF; jedes andere bleibt ein WORD. Das ist die tabellengestützte Alternative dazu, jedes Schlüsselwort vor dem Bezeichner als Token zu deklarieren.

Ein Token verfeinern

@refine hängt Code an eine Token-Definition. Nach Modul- und Funktionsname listet es jeden Namen, zu dem das Token werden kann; die Funktion sieht Text und Position des Tokens und alle Tokens davor. Damit lässt sich JavaScripts / als Division vom Beginn eines Regex-Literals unterscheiden:

SLASH := "/" @refine("JS.SlashDisambiguator", "refine", DIV, REGEX_START)

Ein Token darf eine @keywords-Tabelle oder ein @refine haben, nicht beides.

Native Tokens und Regeln

@native("Module", "function", dep, …) ersetzt den Rumpf eines Tokens oder einer Regel durch handgeschriebenen Code — für das, was keine feste Grammatik ausdrücken kann: Heredocs, deren Endmarke aus der Eingabe gelesen wird, String-Interpolation, Operatortabellen, die sich beim Lesen einer Datei ändern. Die Namen nach der Funktion sind die einzigen Regeln, in die der Code zurückrufen darf, und so sehen die Prüfungen der Grammatik sie weiterhin.

RESOLVER_REF_RAW := @native("Cooper.Native.ResolverRef", "scan")

expr := @native("Prolog.Grammar", "parse_term", primary)
        @hint(nullable: false, leading: (primary))

Das erste stammt aus CASC: Ein !{…}-Verweis darf Klammern verschachteln, und das kann kein festes Token zählen. Ein @native auf Token-Ebene muss die ganze Definition sein. @hint liefert die Fakten, die die Grammatik aus Code nicht ableiten kann: nullable:, ob es nichts erfassen kann, und für Regeln leading:, welche Abhängigkeiten am Anfang stehen können.