Xtext语法定义:可选数组维度的处理方案咨询
解决Xtext中空维度数组的语法与模型访问问题
针对你在定义支持空维度的数组语法时遇到的int[][]这类场景下无法获取维度数量的问题,我给你几个实用的处理方案,从语法重构到模型访问优化都覆盖到了:
方案1:重构语法,把每个维度封装为独立模型元素
这是最清晰也最易维护的方式,把每个[]结构单独抽成一个规则,确保每一对括号都对应一个模型实例,不管里面有没有尺寸表达式:
ArrayType: basicType=BasicType (dimensions+=ArrayDimension)+ ; ArrayDimension: '[' (size=Expression)? ']' ;
这么改之后:
- 像
int[][]这种空维度的情况,dimensions列表会直接包含2个ArrayDimension对象,每个的size属性为null - 对于
int[5][10],两个ArrayDimension实例会分别持有对应的尺寸表达式
后续处理空维度默认值的话,有两种简单方式:
- 模型访问时动态处理:写个工具方法遍历
dimensions,遇到size为null就返回默认值0 - 通过EMF派生特征固化:在你的genmodel里给
ArrayDimension的size配置派生逻辑,当原始值为空时自动返回0(可以用Xtext的@Derived注解或者手动调整EMF模型)
方案2:保留原语法,直接从语法结构获取维度数量
如果你不想改动核心语法规则,其实可以绕开dimension列表的问题——因为('['(dimension+=Expression)?']')+这个重复组的执行次数,本质就是数组的维度数,不管有没有匹配到Expression。
在Xtext生成的Java模型类里,你可以通过访问AST的重复组信息来获取次数,比如给ArrayType添加一个自定义方法:
public int getDimensionCount() { // 这里的Group对应语法里的重复组,size就是[]的数量 return ((ArrayTypeImpl) this).getGroup().size(); }
至于空维度的默认值,只需要在读取dimension列表时做个判断:如果某个位置的Expression是null,就视为0即可。
方案3:用语义挂钩自动填充默认值
如果你希望在模型初始化时就把空维度的默认值补上,可以利用Xtext的语义序列化钩子,或者在生成的模型类里扩展初始化逻辑。比如在ArrayTypeImpl里重写相关方法:
@Override protected void eSet(int featureID, Object newValue) { super.eSet(featureID, newValue); // 检查dimension列表,为空的位置自动创建表示0的表达式 if (featureID == YourDslPackage.ARRAY_TYPE__DIMENSION) { List<Expression> dims = getDimension(); for (int i = 0; i < dims.size(); i++) { if (dims.get(i) == null) { LiteralExpression zeroExpr = YourDslFactory.eINSTANCE.createLiteralExpression(); zeroExpr.setValue("0"); dims.set(i, zeroExpr); } } } }
不过这种方式要注意:如果直接修改生成的代码,下次重新生成Xtext模型会覆盖掉,建议用Xtend写扩展类来覆盖默认行为,或者在genmodel里配置自定义实现类。
内容的提问来源于stack exchange,提问作者Elkfrawy
相关产品推荐
相关产品推荐

