为什么xtext枚举会污染关键字?

时间:2016-06-21 03:23:27

标签: enums keyword dsl xtext

以下是我的语法:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
    greetings+=Table*;

Table:
    'table' name=ID type=Type

;

enum Type: COLUMN | ROW;

以下字符串无效实例:

table ROW COLUMN

这是关键词污染吗? ROW可以充当表的名称。为什么xtext会将其视为一个类型?它有确定它的背景。

我误解了什么吗?我怎么能避免这种事呢?

1 个答案:

答案 0 :(得分:0)

这是xtext枚举的工作原理。枚举文字成为关键字。

你基本上有两个选择

(1)摆脱关键词遮蔽ID规则

Table:
    'table' name=MyID type=Type

;

MyID: ID | "COLUMN" | "ROW";

可能需要针对MyID修改proposalprovider

(2)以不同的方式处理枚举。这适用于仅手动维护的元模型

MyEnum returns importedPackage::MyEnum : ID;
  • 采用值转换器和内容辅助,以便在编辑时获得正确的解析错误和正确的提案

实施例

Model:
    greetings+=Greeting*;

Greeting:
    'Hello' name=ID value=MyEnumDataTypeRule;

//TO be save MyEnum wold be better declared in a separate metamodel
// for sake of easyness i work here with literals that seem to be unlikely to conflict
// to tell xtext there are literals A B and C
enum MyEnum:
    A="___________a"|
    B="___________b"|
    C="___________c"
;

MyEnumDataTypeRule returns MyEnum:
    ID
;

价值转换器

class MyDslValueConverters extends DefaultTerminalConverters {

    @Inject
    MyEnumValueConverter myEnumValueConverter

    @ValueConverter(rule = "MyEnumDataTypeRule")
    def IValueConverter<MyEnum> MyEnumDataTypeRule() {
        return myEnumValueConverter
    }

}

class MyEnumValueConverter implements IValueConverter<MyEnum> {

    override toString(MyEnum value) throws ValueConverterException {
        return value.getName();
    }

    override toValue(String string, INode node) throws ValueConverterException {
        try {
            return MyEnum.valueOf(string)
        } catch (IllegalArgumentException e) {
            throw new ValueConverterException("MyEnum does not allow literal " + string, node, e)
        }

    }

    def static void main(String[] args) {
        MyEnum.valueOf("xxxx")
    }

}

结合

class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {

    override bindIValueConverterService() {
        MyDslValueConverters
    }

}

内容辅助

class MyDslProposalProvider extends AbstractMyDslProposalProvider {

    override complete_MyEnumDataTypeRule(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
        MyEnum.values.forEach[
            acceptor.accept(createCompletionProposal(getName(),context))
        ]
    }

}