更改特殊元素的解析器分隔符

时间:2015-09-02 12:56:56

标签: xtext

以下是我正在努力定义的语言的简化实例:

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规则的实例而不是终端?

感谢您的支持

1 个答案:

答案 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' )*     ;