ANTLR
Lexer regels in v4
Zoeken…
Eenvoudige regels
Lexer-regels definiëren tokensoorten. Hun naam moet beginnen met een hoofdletter om ze te onderscheiden van parserregels.
INTEGER: [0-9]+;
IDENTIFIER: [a-zA-Z_] [a-zA-Z_0-9]*;
OPEN_PAREN: '(';
CLOSE_PAREN: ')';
Basissyntaxis:
| Syntaxis | Betekenis |
|---|---|
A | Overeenkomen met lexerregel of fragment met de naam A |
AB | Wedstrijd A gevolgd door B |
(A|B) | Overeenkomen met A of B |
'text' | Overeenkomen met letterlijke "tekst" |
A? | Match A nul of een keer |
A* | Match A nul of meer keer |
A+ | Match A een of meerdere keren |
[A-Z0-9] | Overeenkomen met één teken in de gedefinieerde bereiken (in dit voorbeeld tussen AZ of 0-9) |
'a'..'z' | Alternatieve syntaxis voor een tekenbereik |
~[AZ] | Ontkenning van een bereik - zoek een willekeurig teken dat niet in het bereik voorkomt |
. | Zoek een willekeurig karakter |
fragmenten
Fragmenten zijn herbruikbare delen van lexerregels die niet op zichzelf kunnen matchen - er moet naar worden verwezen vanuit een lexerregel.
INTEGER: DIGIT+
| '0' [Xx] HEX_DIGIT+
;
fragment DIGIT: [0-9];
fragment HEX_DIGIT: [0-9A-Fa-f];
Impliciete lexerregels
Wanneer tokens zoals '{' worden gebruikt in een parserregel , wordt er een impliciete lexerregel voor gemaakt, tenzij er een expliciete regel bestaat.
Met andere woorden, als u een lexerregel hebt:
OPEN_BRACE: '{';
Dan zijn beide parserregels equivalent:
parserRule: '{';
parserRule: OPEN_BRACE;
Maar als de OPEN_BRACE niet is gedefinieerd, wordt een impliciete anonieme regel gemaakt. In dat geval wordt de impliciete regel gedefinieerd alsof deze vóór de andere regels is gedefinieerd: deze heeft een hogere prioriteit dan andere regels.
Prioriteitsregels
Verschillende lexerregels kunnen overeenkomen met dezelfde invoertekst. In dat geval wordt het tokentype als volgt gekozen:
- Selecteer eerst de lexerregel die overeenkomt met de langste invoer
- Als de tekst overeenkomt met een impliciet gedefinieerd token (zoals
'{'), gebruikt u de impliciete regel - Als verschillende lexerregels overeenkomen met dezelfde invoerlengte, kiest u de eerste op basis van de volgorde van de definities
De volgende gecombineerde grammatica:
grammar LexerPriorityRulesExample;
// Parser rules
randomParserRule: 'foo'; // Implicitly declared token type
// Lexer rules
BAR: 'bar';
IDENTIFIER: [A-Za-z]+;
BAZ: 'baz';
WS: [ \t\r\n]+ -> skip;
Gegeven de volgende input:
aaa foo bar baz barz
Zal de volgende tokensequentie van de lexer produceren:
IDENTIFIER 'foo' BAR IDENTIFIER IDENTIFIER
aaais van het typeIDENTIFIERAlleen de
IDENTIFIERregel kan overeenkomen met dit token, er is geen onduidelijkheid.
foois van het type'foo'De
randomParserRuleintroduceert het impliciete'foo'randomParserRule, dat prioriteit heeft boven deIDENTIFIERregel.
baris van het typeBARDeze tekst komt overeen met de
BARregel, die is gedefinieerd vóór deIDENTIFIERregel, en heeft daarom voorrang.
bazis van het typeIDENTIFIERDeze tekst komt overeen met de
BAZregel, maar het komt ook overeen met deIDENTIFIERregel. De laatste wordt gekozen zoals deze is gedefinieerd voorBAR.Gezien de grammatica zal
BAZnooit kunnen matchen, omdat deIDENTIFIERregel al alles omvat watBAZkan evenaren.
barzis van het typeIDENTIFIERDe
BARregel kan overeenkomen met de eerste 3 tekens van deze tekenreeks (bar), maar deIDENTIFIERregel komt overeen met 4 tekens. OmdatIDENTIFIERovereenkomt met een langere substring, wordt deze gekozen bovenBAR.
Als vuistregel moeten specifieke regels worden gedefinieerd vóór meer generieke regels. Als een regel alleen kan overeenkomen met een invoer die al onder een eerder gedefinieerde regel valt, wordt deze nooit gebruikt.
Impliciet gedefinieerde regels zoals 'foo' doen alsof ze vóór alle andere lexerregels zijn gedefinieerd.
Lexer-opdrachten
Een lexerregel kan bijbehorende opdrachten hebben :
WHITESPACE: [ \r\n] -> skip;
Commando's worden gedefinieerd na een -> aan het einde van de regel.
-
skip:skipde overeenkomende tekst over, er wordt geen token verzonden -
channel(n): zendt het token uit op een ander kanaal -
type(n): Wijzigt het uitgezonden tokentype -
mode(n),pushMode(n),popMode,more: Regelt lexermodi
Acties en semantische predikaten
Een lexeractie is een blok willekeurige code in de doeltaal omgeven door { ... } , dat wordt uitgevoerd tijdens het matchen:
IDENTIFIER: [A-Z]+ { log("matched rule"); };
Een semantisch predicaat is een blok willekeurige code in de doeltaal, omringd door { ... }? , wat resulteert in een booleaanse waarde. Als de geretourneerde waarde onwaar is, wordt de lexerregel overgeslagen.
IDENTIFIER: [A-Z]+ { identifierIsValid() }?;
Semantische predikaten moeten om prestatieredenen waar mogelijk aan het einde van de regel worden gedefinieerd.