以下是我正在努力定义的语言的简化实例:
test : potato_good
test2 : carrot_not_that_good
B_test = help
C_test = 13
B_test2 = me
C_test2 = 37
您可以注意到,实例的第一部分是某些元素的声明。
第二部分包含对这些元素的两种引用。我们将它们称为B和C引用,每个引用都有不同的语义。
我第一次尝试定义这样的语言是这样的:
Model : A* (B|C)* ;
A: name=ID ':' ID ;
B: 'B_'[A] '=' ID ;
C: 'C_'[A] '=' NUMBER;
Terminal ID: ('a'..'z' | 'A'..'Z' | 0..9 | '_')* ;
Terminal NUMBER: ( 0..9 )* ;
此定义的问题在于编辑器会在前缀'B_'
或'C_'
与对元素A
的引用之间留出空格。
你如何做到这一点,解析器可以识别出一种类型的字符串' B_test'作为B规则的实例而不是终端?
感谢您的支持
答案 0 :(得分:0)
这是一个词法问题。因为词法分析器在解析器之前运行并且是无状态的,所以它始终是一个ID。也许你可以尝试使用自定义词法分析器来解决这个问题(不知道是否有办法在antlr中解决这个问题)
作为一种解决方法,您可以尝试以下方法,但这不是一般解决方案
Model : ase+=A* bcs+=(B|C)* ;
A: name=ID ':' value=ID ;
B: 'B_' ref=[A] '=' value=ID ;
C: 'C_' ref=[A] '=' value=NUMBER;
terminal ID: ('a'..'z' | 'A'..'Z' | '0'..'9' | '_') |
( ('B'|'C')('a'..'z' | 'A'..'Z' | '0'..'9') ) |
( ('A'| ('D'..'Z') | 'a'..'z')('a'..'z' | 'A'..'Z' | '0'..'9' |'_')+ )
;
terminal NUMBER: ( '0'..'9' )* ;