如何解析限定名称表达式中的字段
How to resolve field in qualifed name expression
这是我的 'Types' Xtext 语法:
grammar sample.types.Types with org.eclipse.xtext.common.Terminals
generate 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
;
这里是 'Types' 语法的一个实例:
struct SampleA {
number n
string s
}
struct SampleB {
number n
string s
}
SampleA sampleA1
SampleA sampleA2
SampleB sampleB
sampleA1.n = 12
sampleA1.s = "Hello"
sampleA2.n = 12
sampleA2.s = "Hello"
sampleB.n = 42
sampleB.s = "Hello"
引用字段 'n' 和 's' 的最后六行生成错误:
Couldn't resolve reference to Field '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 )
}
}
在你的语法中你有
QName:
data=[Data|ID] '.' path=[Field|ID]
;
因此 a.b
将被限定为两个引用。因此,您要么必须在您的范围 probvider
中反映这一点
// 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)?;
这是我的 'Types' Xtext 语法:
grammar sample.types.Types with org.eclipse.xtext.common.Terminals
generate 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
;
这里是 'Types' 语法的一个实例:
struct SampleA {
number n
string s
}
struct SampleB {
number n
string s
}
SampleA sampleA1
SampleA sampleA2
SampleB sampleB
sampleA1.n = 12
sampleA1.s = "Hello"
sampleA2.n = 12
sampleA2.s = "Hello"
sampleB.n = 42
sampleB.s = "Hello"
引用字段 'n' 和 's' 的最后六行生成错误:
Couldn't resolve reference to Field '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 )
}
}
在你的语法中你有
QName:
data=[Data|ID] '.' path=[Field|ID]
;
因此 a.b
将被限定为两个引用。因此,您要么必须在您的范围 probvider
// 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)?;