我的语法看起来像这样(简化显示问题):
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) }
我得到"不匹配的输入' COMMAND1'期待FUNCTIONNAME2"
如何让这种情况发挥作用?即两个代码块都可以包含相同的函数名吗?
答案 0 :(得分:0)
基本问题是词法分析器将始终指定“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' ;