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 type IDENTIFIER

    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 de IDENTIFIER regel.

  • bar is van het type BAR

    Deze tekst komt overeen met de BAR regel, die is gedefinieerd vóór de IDENTIFIER regel, en heeft daarom voorrang.

  • baz is van het type IDENTIFIER

    Deze tekst komt overeen met de BAZ regel, maar het komt ook overeen met de IDENTIFIER regel. De laatste wordt gekozen zoals deze is gedefinieerd voor BAR .

    Gezien de grammatica zal BAZ nooit kunnen matchen, omdat de IDENTIFIER regel al alles omvat wat BAZ kan evenaren.

  • barz is van het type IDENTIFIER

    De BAR regel kan overeenkomen met de eerste 3 tekens van deze tekenreeks ( bar ), maar de IDENTIFIER regel komt overeen met 4 tekens. Omdat IDENTIFIER overeenkomt met een langere substring, wordt deze gekozen boven BAR .

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.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow