字符串常量在xtext中导致意外类型冲突

时间:2013-11-27 21:04:36

标签: parsing antlr grammar xtext

我把这个问题简化为一个非常简单的语法。

Model:
    (greetings+=Greeting* | greetings+=FrGreeting*);

Greeting:
    'Hello' person=ID '!';

FrGreeting:
    'Bonjour' person=('jacques' | 'philippe') '!';

在文件中,您可以用英语或法语来问候,但不能同时用两者。我们只知道2名法国人的名字。

问题是你不能用英语问候雅克。

Hello jacques!

结果为mismatched input 'jacques' expecting RULE_ID。我很困惑为什么会这样。我该如何解决?

修改 做这样的事情:

Greeting:
    'Hello' person= AllNames '!';

FrGreeting:
    'Bonjour' person=(FrenchNames) '!';

AllNames: ID | FrenchNames ;

FrenchNames: 'jacques' | 'philippe';

修复了编译错误问题。但是,它会阻止自动完成工作,jacquesphilippe仍然会像关键字一样突出显示(即使写为Hello jacques!)。

编辑2: 这似乎解决了自动完成错误:

Greeting:
    'Hello' person= AllNames '!';

FrGreeting:
    'Bonjour' person=('jacques' | 'philippe') '!';

AllNames: 'jacques' | 'philippe' | ID;

我的问题: 为什么1分支中的字符串常量会改变ID终端沿不同代码路径被摄取的方式?它是用终端实现的(这似乎与文档相矛盾)?这是一个错误吗?

我编辑的解决方案是否是实现此目标的最佳方式?

2 个答案:

答案 0 :(得分:1)

这个语法对我来说没有多大意义,但我猜(如果我理解正确的话)你可以用以下方法做你想做的事:

Model:
  (greetings+=Greeting* | greetings+=FrGreeting*);

Greeting:
  'Hello' person=PersonName '!';

FrGreeting:
  'Bonjour' person=PersonName '!';

PersonName : ID | 'jacques' | 'philippe';

答案 1 :(得分:1)

你正是解决问题的正确方法。并且,你接近原因。 原因是语法中的常量字符串是TOKEN。该ID也是一个令牌。它们都是词法术语。但“常量字符串”TOKEN被视为“关键字”。它比其他TOKEN具有更高的优先级。因此,当您在编辑器中输入“jacques”时,解析器会看到令牌“jacques”而不是令牌ID。但是,“问候”规则需要一个令牌ID。