如何共享不同标记的值 - 不匹配的输入 'COMMAND1' 期望 FUNCTIONNAME2" -

How to share values for different tokens - mismatched input 'COMMAND1' expecting FUNCTIONNAME2" -

我的语法如下所示(经过简化以显示问题):

parse
    : block EOF
    ;

block
    : TYPE1 OPAR STRING CPAR type1_statement_block      
    | TYPE2 OPAR STRING CPAR type2_statement_block          
    ;

type1_statement_block
    : OBRACE function1+ CBRACE                  
    ;

function1
    : FUNCTIONNAME1 OPAR (parameter (',' parameter)*)? CPAR     
    ;

FUNCTIONNAME1 : 'COMMAND1';

type2_statement_block
    : OBRACE function2+ CBRACE                  
    ;

function2
    : FUNCTIONNAME2 OPAR (parameter (',' parameter)*)? CPAR     
    ;

FUNCTIONNAME2 : 'COMMAND1' | 'COMMAND2'

parameter
    : INT                               
    ;

OPAR : '(';
CPAR : ')';
OBRACE : '{';
CBRACE : '}';
TYPE1 : 'TYPE1';
TYPE2 : 'TYPE2';

INT
     : [0-9]+
     ;

STRING
 : '"' (~["\r\n] | '""')* '"'
 ;

SPACE
 : [ \t\r\n] -> skip
 ;

ErrChar
  : .
  ;

解析以下字符串工作正常:

TYPE1 ("abc") { COMMAND1(0) }
TYPE2 ("abc") { COMMAND2(0) }

但是解析以下字符串会导致错误

TYPE2 ("abc") { COMMAND1(0) }

我得到"mismatched input 'COMMAND1' expecting FUNCTIONNAME2"

我怎样才能让这个场景起作用? IE。两个代码块可以包含相同的函数名称吗?

基本问题是词法分析器总是将 'COMMAND1' 分配给标记 FUNCTIONNAME1,因为该规则首先出现,并且与规则 FUNCTIONNAME2 相关的所有其他词法要求都相同。您可以合并 FUNCTIONNAME1/2 规则,但这会导致第二个语法问题。

如所写,语法试图在 'Type1' 和 'Type2' 语句之间施加语义区别,这些语句在其他方面语法相同。更好的做法是使用文法进行句法分析并延迟树遍历的语义分析。关注点分离将使两者变得更容易。

block
    : ( cmd OPAR STRING CPAR statement_block )+
    ;

statement_block
    : OBRACE function+ CBRACE
    ;

function
    : FUNCTIONNAME OPAR (parameter (',' parameter)*)? CPAR     
    ;

cmd : 'TYPE1' | 'TYPE2' ;
FUNCTIONNAME : 'COMMAND1' | 'COMMAND2' ;