ANTLR v4:相同的字符在不同的上下文中有不同的含义

ANTLR v4:相同的字符在不同的上下文中有不同的含义,antlr,grammar,lexer,antlr4,Antlr,Grammar,Lexer,Antlr4,这是我在解析器生成器方面的第一次尝试,因此也是ANTLR。我正在使用ANTLR v4,试图为摩尔斯电码生成一个简单的实践解析器,其中包含以下额外规则: 一个字母(例如,..[字母的'])如果前面有一个'^',则可以表示为大写 例:^…表示资本的 特殊字符可以嵌入括号中 例:(@) 每个编码实体将用空格分隔 所以我可以对下面的句子进行编码: ABCa@b.com as(下面显示了相应的字母): 特别注意以下两个实体:()(表示空格)和()(表示句点) 有一件事我很难理解:同一个标记可能会有

这是我在解析器生成器方面的第一次尝试,因此也是ANTLR。我正在使用ANTLR v4,试图为摩尔斯电码生成一个简单的实践解析器,其中包含以下额外规则:

  • 一个字母(例如,
    ..
    [字母的'])如果前面有一个'^',则可以表示为大写
    • 例:
      ^…
      表示资本的
  • 特殊字符可以嵌入括号中
    • 例:
      (@)
  • 每个编码实体将用空格分隔
  • 所以我可以对下面的句子进行编码:

    ABCa@b.com

    as(下面显示了相应的字母):

    特别注意以下两个实体:
    ()
    (表示空格)和
    ()
    (表示句点)

    有一件事我很难理解:同一个标记可能会有不同的含义,这取决于它是否在括号中。也就是说,我想告诉ANTLR我想丢弃空白,但不是在
    ()
    的情况下。此外,莫尔斯电码字符可以由点和破折号组成(期间和破折号),但是,我不想把<代码>(<)/>代码中的句号视为“任何字符”。 以下是我目前掌握的语法:

    grammar MorseCode;
    
    file: entity*;
    
    entity:
          special
        | morse_char;
    
    special: '(' SPECIAL ')';
    
    morse_char: '^'? (DOT_OR_DASH)+;
    
    SPECIAL     : .; // match any character
    DOT_OR_DASH : ('.' | '-');
    
    WS          : [ \t\r\n]+ -> skip; // we don't care about whitespace (or do we?)
    
    当我针对以下输入进行尝试时:

    ^... --- ...(@)
    
    我得到以下输出(来自
    grun…-tokens
    ):

    [@0,0:0='^',1:0]
    [@1,1:1='.',,1:1]
    ...
    [@15,15:14='',,1:15]
    第1行:1输入“.”不匹配,应为点或破折号
    
    SPECIAL
    DOT\u或破折号
    之间似乎存在歧义问题。

    您的
    (@)
    语法的行为类似于其他编程语言中引用的字符串。我首先将
    SPECIAL
    定义为:

    SPECIAL : '(' .*? ')';
    
    要确保
    实际上是不同的,您可以使用以下方法:

    SYMBOL : [.-]+;
    
    然后,您可以定义
    ^
    运算符:

    CARET : '^';
    
    使用这三个标记(并保持
    WS
    不变),您可以显著简化解析器规则:

    file
      : entity* EOF
      ;
    
    entity
      : morse_char
      | SPECIAL
      ;
    
    morse_char
      : CARET? SYMBOL
      ;
    

    果不其然,这就是诀窍…还不知道为什么--现在开始分析。所以我的困惑似乎是“我该如何定义lexer规则和parser规则?”。例如,你将“special”改为lexer规则,对吗?你有一个思维过程来帮你决定吗?还是我只需要--吞咽--练习?哈哈
    CARET : '^';
    
    file
      : entity* EOF
      ;
    
    entity
      : morse_char
      | SPECIAL
      ;
    
    morse_char
      : CARET? SYMBOL
      ;