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
aaa
is van het typeIDENTIFIER
Alleen de
IDENTIFIER
regel kan overeenkomen met dit token, er is geen onduidelijkheid.
foo
is van het type'foo'
De
randomParserRule
introduceert het impliciete'foo'
randomParserRule
, dat prioriteit heeft boven deIDENTIFIER
regel.
bar
is van het typeBAR
Deze tekst komt overeen met de
BAR
regel, die is gedefinieerd vóór deIDENTIFIER
regel, en heeft daarom voorrang.
baz
is van het typeIDENTIFIER
Deze tekst komt overeen met de
BAZ
regel, maar het komt ook overeen met deIDENTIFIER
regel. De laatste wordt gekozen zoals deze is gedefinieerd voorBAR
.Gezien de grammatica zal
BAZ
nooit kunnen matchen, omdat deIDENTIFIER
regel al alles omvat watBAZ
kan evenaren.
barz
is van het typeIDENTIFIER
De
BAR
regel kan overeenkomen met de eerste 3 tekens van deze tekenreeks (bar
), maar deIDENTIFIER
regel komt overeen met 4 tekens. OmdatIDENTIFIER
overeenkomt 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
:skip
de 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.