ANTLR(Lexer):将任意标识符与关键字分开

问题描述 投票:0回答:1

我正在尝试为bat / cmd文件创建一个(简单的)Lexer(用于语法着色)。作为此任务的一部分,我需要将关键字与(任意)标识符分开。但是根据this answer,ANTLR尝试让最长的比赛胜过较短的比赛。到目前为止,我的语法看起来像这样

lexer grammar CmdLexer;

Identifier
    : IdentifierNonDigit
      (  IdentifierNonDigit
      |  Digit
      )+
    ;

Number
    : Digit+
    ;

fragment IdentifierNonDigit
    : [a-zA-Z_\u0080-\uffff]
    ;

fragment Digit
    : [0-9]
    ;

Punctuation
    : [\u0021-\u002f\u003a-\u0040\u005b-\u0060\u007b-\u007f]+
    ;

Keyword
    : A P P E N D
    | A T
    | A T T R I B
    | B R E A K
    | C A L L
    | C D
    | C H C P
    | C H D I R
    | C L S
    | C O L O R
    | C O P Y
    | D A T E
    | D E L
    | D I R
    | D O
    | E C H O
    | E D I T
    | E N D L O C A L
    | E Q U
    | E X I S T
    | E X I T
    | F C
    | F O R
    | F T Y P E
    | G O T O
    | G E Q
    | G T R
    | I F
    | I N
    | L E Q
    | L S S
    | M D
    | M K D I R
    | M K L I N K
    | M O R E
    | M O V E
    | N E Q
    | N O T
    | N U L
    | P A T H
    | P A U S E
    | P O P D
    | P U S H D
    | R D
    | R E N
    | R E N A M E
    | S E T
    | S E T L O C A L
    | S H I F T
    | S T A R T
    | T I T L E
    | T R E E
    | T Y P E
    | W H E R E
    | W H O A M I
    | X C O P Y
    ;

fragment A:('a'|'A');
fragment B:('b'|'B');
fragment C:('c'|'C');
fragment D:('d'|'D');
fragment E:('e'|'E');
fragment F:('f'|'F');
fragment G:('g'|'G');
fragment H:('h'|'H');
fragment I:('i'|'I');
fragment J:('j'|'J');
fragment K:('k'|'K');
fragment L:('l'|'L');
fragment M:('m'|'M');
fragment N:('n'|'N');
fragment O:('o'|'O');
fragment P:('p'|'P');
fragment Q:('q'|'Q');
fragment R:('r'|'R');
fragment S:('s'|'S');
fragment T:('t'|'T');
fragment U:('u'|'U');
fragment V:('v'|'V');
fragment W:('w'|'W');
fragment X:('x'|'X');
fragment Y:('y'|'Y');
fragment Z:('z'|'Z');

Whitespace
    : [ \t]+
      -> skip
    ;

Newline
    : ( '\r' '\n'?
      | '\n'
      )
      -> skip
    ;

LineComment
    : ( '@'? R E M ~[\r\n]*
      | '@'? '::' ~[\r\n]*
      )
      -> skip
    ;

但它始终将所有内容都匹配为Identifier,甚至是appendCALL之类的单词。我在这里看不到模式如何解决此问题,但如何给某个规则更高的优先级(此处Keyword高于其他规则(此处Identifier)?

antlr antlr4 lexer
1个回答
0
投票

但是根据这个答案,ANTLR试图让最长的比赛胜过较短的比赛。

确实如此,那应该是您想要的。请注意,此规则(所谓的最大munch规则)与append是否匹配为关键字或标识符无关。与appendix是否与关键字append相匹配,后跟标识符ix有关;或作为单个标识符appendix。由于后者显然是大多数情况下想要的,因此最大的munch规则很有用。

在这种情况下,重要的是,如果多个规则产生相同长度的匹配项,将会发生什么。在这种情况下,ANTLR将应用语法中首先定义的规则。因此,如果您更改定义的顺序,以使KeywordIdentifier之前,则在两个规则产生相同长度的匹配项时,Keyword规则将优先(并且最长的匹配项仍会获胜)情况并非如此)。因此,像append appendix这样的输入将被标记为关键字append,后跟标识符appendix,这应该是您想要的。

PS:我不确定您的词法分析器将在何处/如何使用,但是通常您希望区分不同的关键字,而不是使用一个匹配所有关键字的规则。如果令牌将用作解析器的输入,则在不知道它是哪个关键字的情况下,某些东西是关键字的信息不是很有用。

© www.soinside.com 2019 - 2024. All rights reserved.