【问题标题】:Why xtext enum pollutes the keywords?为什么 xtext 枚举会污染关键字?
【发布时间】:2016-06-21 03:23:26
【问题描述】:

以下是我的语法:

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 将其视为类型?它有上下文来确定它。

我是不是误会了什么?我怎样才能避免这种事情?

【问题讨论】:

    标签: enums keyword dsl xtext


    【解决方案1】:

    这就是 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))
            ]
        }
    
    }
    

    【讨论】:

    • 感谢您的回答,您能否提供有关选项 2 的更多详细信息。如果有示例,将会很有帮助。 @Christian
    • 添加了一个例子。虽然我欺骗了外部元模型
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多