Xtext语法如何实现元素属性同时支持参数引用与字面量直接赋值
问题原因
你之前的整数场景能正常运行,是因为参数引用(匹配ID)和整数字面量(匹配DECINT)的词法类型完全不重叠,ANTLR可以无歧义识别。但第一次修改的字符串语法存在歧义:StringRefParameter和StringLiteral都可以匹配ID或带引号的STRING,词法规则重叠导致ANTLR代码生成中断,才会报Lexer文件找不到的错误。
解决方案
对齐整数场景的语法设计,明确区分字符串引用和字符串字面量的匹配规则即可,有两种常用实现方案:
方案1:和整数逻辑完全对齐
- 字符串参数引用匹配无引号的ID
- 字符串字面量强制匹配带引号的STRING
完整可运行语法
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals generate myDsl "http://www.xtext.org/example/mydsl/MyDsl" import "http://www.eclipse.org/emf/2002/Ecore" as ecore Model: stringParameters+=StringParameter* intParameters+=IntParameter* elements+=Element* otherElements+=AnotherElement* ; // 字符串值规则:支持引用或字面量 StringValue: ref=[StringParameter] | literal=STRING ; // 整数值规则:和你之前正常运行的版本一致 IntValue: ref=[IntParameter] | literal=DECINT ; StringParameter returns StringParameter: {StringParameter} 'StringParameter' name=ID '{' ('value' value=STRING)? '}'; IntParameter returns IntParameter: {IntParameter} 'IntParameter' name=ID '{' ('value' value=DECINT)? '}'; Element returns Element: 'Element' '{' 'name' value=StringValue '}'; AnotherElement returns AnotherElement: 'AnotherElement' '{' 'value' value=IntValue '}'; terminal fragment DIGIT: '0'..'9'; terminal DECINT: '0' | ('1'..'9' DIGIT*) | ('-' ('0'..'9') DIGIT*) ;
测试用例(可正常解析)
StringParameter test { value "hello" } IntParameter dummy { value 4 } Element { name test } // 引用字符串参数,正常 Element { name "blah" } // 字符串字面量,正常 AnotherElement { value dummy } // 引用整数参数,正常 AnotherElement { value 7 } // 整数字面量,正常
方案2:贴合你最初的XML宏设计
如果需要支持无引号的字符串字面量,可以给参数引用加上${}包裹标识,和你最开始的XML宏示例语法对齐,完全避免歧义:
调整StringValue规则即可
StringValue: ref=StringRef | literal=EString ; StringRef: '${' ref=[StringParameter] '}' ; EString returns ecore::EString: STRING | ID ;
对应测试用例
StringParameter test { value "hello" } Element { name ${test} } // 引用参数 Element { name blah } // 无引号字符串字面量 Element { name "blah" } // 带引号字符串字面量
内容的提问来源于stack exchange,提问作者harsh
相关产品推荐
相关产品推荐

