为了账号安全,请及时绑定邮箱和手机立即绑定

如何解析限定名称表达式中的字段

如何解析限定名称表达式中的字段

呼唤远方 2023-06-28 15:43:29
这是我的“类型”Xtext 语法:grammar sample.types.Types with org.eclipse.xtext.common.Terminalsgenerate types "http://www.types.sample/Types"Model:    structs     += Struct*    data        += Data*    assignments += Assignment*;Struct:    'struct' name=ID '{'        fields += Field*    '}';Field:    type=Type name=ID;Type:      'number'    | 'string';Data:    type=[Struct|ID] name=ID;Assignment:    qname=QName '=' value=Value;QName:    data=[Data|ID] '.' path=[Field|ID];Value:      INT    | STRING;这是“类型”语法的一个实例:struct SampleA {    number n    string s}struct SampleB {    number n    string s}SampleA sampleA1SampleA sampleA2SampleB sampleBsampleA1.n = 12sampleA1.s = "Hello"sampleA2.n = 12sampleA2.s = "Hello"sampleB.n  = 42sampleB.s  = "Hello"最后六行引用字段“n”和“s”,生成错误:无法解析对字段“x”的引用。我编写了以下自定义范围提供程序,但没有成功:class TypesScopeProvider extends AbstractTypesScopeProvider {   override getScope( EObject context, EReference reference ) {      if( reference === TypesPackage.Literals.QNAME__PATH ) {         val model = EcoreUtil2.getContainerOfType(context, Model)         if( model !== null ) {            val result = newArrayList            for( data : model.data ) {               for( field : data.type.fields ) {                  result.add(                     EObjectDescription.create(                        QualifiedName.create( data.name, field.name ),                        field ))               }            }            return new SimpleScope(IScope.NULLSCOPE, result)         }      }      super.getScope( context, reference )   }}
查看完整描述

1 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

在你的语法中你有


QName:

    data=[Data|ID] '.' path=[Field|ID]

;

因此a.b将成为两个参考的范围。因此你要么必须在你的范围提供商中反映这一点


// TODO: context will be a qname. ask it for its data. ask that for its data and collect fields from there and then

// scope for path

EObjectDescription.create(

                    QualifiedName.create(field.name ),

                    field ))

例如


override getScope(EObject context, EReference reference) {

    if (reference === MyDslPackage.Literals.QNAME__PATH) {

        if (context instanceof QName) {

            val result = newArrayList

            for (field : context.data.type.fields) {

                result.add(EObjectDescription.create(QualifiedName.create(field.name), field))

            }

            System.err.println(result)

            return new SimpleScope(IScope.NULLSCOPE, result)


        }

    }

    super.getScope(context, reference)

}

或者你有语法来反映你的范围


DataOrField: Data | Field;

QName: dataOrField=[DataOrField|FQN]

FQN: ID ("." ID)?;


查看完整回答
反对 回复 2023-06-28
  • 1 回答
  • 0 关注
  • 137 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信