no suggestions for node (xpath) [message #734132] |
Thu, 06 October 2011 19:53 |
gary s thompson Messages: 92 Registered: July 2009 |
Member |
|
|
i am trying to produce an xpath like grammar editor and have the following (there is a bit more but this is the fragment that makes up a path once i implemented a scopeprovider)
RelativeLocationPathHead:
step=Step (tail=RelativeLocationPathTail)?
;
RelativeLocationPathTail:
operator+=('/'/* |'//'*/) step=Step (tail=RelativeLocationPathTail)?
;
Step:
axis=AxisSpecifier nodeTest=[ecore::EReference] predicates+=Predicate*
;
AxisName:
FullAxisName '::'| AttributeAxisName
;
AttributeAxisName:
'@'
;
FullAxisName:
'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'
;
AxisSpecifier:
{AxisSpecifier} axisName=AxisName?
;
now I can write the following
windle/nmrProjects/experiments[dataSources/peakLists/peaks/peakDims]
windle/nmrProjects/experiments[preceding-sibling::dataSources/peakLists/peaks/peakDims]
and it all works however, I can't get the text editor to suggest AxisSpecifiers such as preceding-sibling::. But, once they are completed they don't result in a syntax error. Does anyone have a suggestion of whats wrong or what I need to do?
regards
gary
for reference here is the complete syntax
// automatically generated by Xtext
grammar uk.ac.leeds.nsxl2.cork.Cork with org.eclipse.xtext.common.Terminals
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate cork "http://www.cork.nsxl2.leeds.ac.uk/cork/Cork"
Cork:
elements+=AbstractElement*;
AbstractElement:
PathDefinition | RootRef
;
RootRef:
Open
;
Open:
'open' name=ID 'from' file=STRING
;
Expression:
OrExpr
;
OrExpr :
expr+=AndExpr /* ('or' expr+=AndExpr)* */
;
AndExpr :
expr+=EqualityExpr /* ('and' expr+=EqualityExpr)* */
;
EqualityExpr
: expr+=relationalExpr /* (operator+=('='|'!=') expr+=relationalExpr)* */
;
relationalExpr
: expr+=AdditiveExpr /* (operator+=('<'|'>'|'<='|'>=') expr+=AdditiveExpr)* */
;
AdditiveExpr
: expr+=MultiplicativeExpr /*(operator+=('+'|'-') expr+=MultiplicativeExpr)* */
;
MultiplicativeExpr:
rootExpr=UnaryExprNoRoot /* (operator+=('*'|'div'|'mod') expr+=MultiplicativeExpr)?
| '/' (operator+=('div'|'mod') expr+=MultiplicativeExpr)? */
;
//Minus:
// '-'
//;
UnaryExprNoRoot
: /*numMinus+=Minus* */ expr=UnionExprNoRoot
;
UnionExprNoRoot
: path=PathExprNoRoot /* ('|' expr+=UnionExprNoRoot)? */
/* | '/' '|' expr+=UnionExprNoRoot */
;
PathExprNoRoot
: path=LocationPath /*
| filter=filterExpr (operator+=('/'|'//') path+=relativeLocationPath)?*/
;
LocationPath:
relativePath=RelativeLocationPathHead
/* | absoluteLocationPathNoroot */
;
RelativeLocationPathHead:
step=Step (tail=RelativeLocationPathTail)?
;
RelativeLocationPathTail:
operator+=('/'/* |'//'*/) step=Step (tail=RelativeLocationPathTail)?
;
Step:
axis=AxisSpecifier nodeTest=[ecore::EReference]/*NCName*/ predicates+=Predicate*
/* | abbreviatedStep=AbbreviatedStep */
;
//NodeTest:
// NameTest
// /* | NodeType '(' ')'
// | 'processing-instruction' '(' Literal ')'*/
// ;
//NameTest:
// /* '*'
// | nCName ':' '*' |*/
// qName=NCName
//
//
//;
//
////QName:
//// nCName+=NCName (':' nCName+=NCName)?
//// ;
//
//NCName:
// nnCName=[ecore::EStructuralFeature] /* | axis=AxisName */
//
//;
AxisName:
FullAxisName '::'| AttributeAxisName
;
AttributeAxisName:
'@'
;
FullAxisName:
'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'
;
AxisSpecifier:
{AxisSpecifier} axisName=AxisName?
;
//
//
//AbbreviatedStep:
// abbreviation=('.' | '..')
//;
PathDefinition:
'path' name=ID ':' head=PathHead;
Predicate:
'[' expression=Expression ']'
;
PathHead:
root=[RootRef] (tail=RelativeLocationPathTail)?;
//PathTail:
// '/' feature=[ecore::EReference] (predicates+=Predicate)* (tail=PathTail)?;
and the scopeprovider
/*
* generated by Xtext
*/
package uk.ac.leeds.nsxl2.cork.scoping;
import java.util.List;
import memops.ecore_api.Implementation.ImplementationPackage;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.eclipse.xtext.scoping.impl.SimpleLocalScopeProvider;
import uk.ac.leeds.nsxl2.cork.cork.CorkPackage;
import uk.ac.leeds.nsxl2.cork.cork.PathHead;
import uk.ac.leeds.nsxl2.cork.cork.Predicate;
import uk.ac.leeds.nsxl2.cork.cork.RelativeLocationPathHead;
import uk.ac.leeds.nsxl2.cork.cork.RelativeLocationPathTail;
/**
* This class contains custom scoping description.
*
* see : http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping on
* how and when to use it
*
*/
public class CorkScopeProvider extends AbstractDeclarativeScopeProvider {
private final static Class<?>[] SCOPE_CONTAINER_TYPES = { RelativeLocationPathTail.class,
RelativeLocationPathHead.class,
PathHead.class};
private final static Class<?>[] PATH_ELEMENT_STEP_CONTAINER_TYPES = { RelativeLocationPathTail.class,
RelativeLocationPathHead.class,
Predicate.class};
@Override
public IScope getScope(EObject context, EReference reference) {
final CorkPackage CORK_EPACKAGE = CorkPackage.eINSTANCE;
final EClass STEP_ECLASS = CORK_EPACKAGE.getStep();
final EClass PATH_HEAD_ECLASS = CORK_EPACKAGE.getPathHead();
final EClass RELATIVE_LOCATION_PATH_HEAD_ECLASS = CORK_EPACKAGE.getRelativeLocationPathHead();
final EClass RELATIVE_LOCATION_PATH_TAIL_ECLASS = CORK_EPACKAGE.getRelativeLocationPathTail();
reportScopeContext(context, reference);
IScope result = null;
EClass referenceContext = (EClass) reference.eContainer();
if (referenceContext.equals(STEP_ECLASS)) {
EObject container = findScopeContainer(context);
if (sameClass(container, PATH_HEAD_ECLASS)) {
result = getScopeForPathHead();
} else if (sameClass(container, RELATIVE_LOCATION_PATH_TAIL_ECLASS)) {
RelativeLocationPathTail pathTail = (RelativeLocationPathTail) container;
result=getScopeForRelativeLocationPathTail(pathTail);
} else if (sameClass(container, RELATIVE_LOCATION_PATH_HEAD_ECLASS)) {
RelativeLocationPathHead relativeLocationPathHead = (RelativeLocationPathHead) container;
result = getScopeForRelativeLocationPathHead((relativeLocationPathHead));
}
}
if (result == null) {
result = super.getScope(context, reference);
}
return result;
}
private boolean sameClass(EObject container, EClass eClass) {
return container.eClass().equals(eClass);
}
private EObject findScopeContainer(EObject context) {
EObject stepContainer = findParentByTypesOrdered(context, PATH_ELEMENT_STEP_CONTAINER_TYPES);
EObject scopeContainer = findParentByTypesOrdered(stepContainer.eContainer(), SCOPE_CONTAINER_TYPES);
if (scopeContainer != null) {
stepContainer = scopeContainer;
}
return stepContainer;
}
private IScope getScopeForRelativeLocationPathTail(
RelativeLocationPathTail container) {
EReference tailReference = (EReference) container.getStep()
.getNodeTest();
IScope result = getScopeFromReference(tailReference);
return result;
}
private IScope getScopeForRelativeLocationPathHead(RelativeLocationPathHead container) {
EReference tailReference = (EReference) container.getStep()
.getNodeTest();
IScope result = getScopeFromReference(tailReference);
return result;
}
private IScope getScopeForPathHead() {
EClass root = ImplementationPackage.eINSTANCE.getMemopsRoot();
List<EReference> structuralFeatures = references(root);
IScope result = Scopes.scopeFor(structuralFeatures);
return result;
}
private void reportScopeContext(EObject context, EReference reference) {
SimpleLocalScopeProvider delegate = (SimpleLocalScopeProvider) getDelegate();
EObject parent = context.eContainer();
System.err.println("---------\n");
System.err.println("containers" + " " + listContainers(context));
System.err.println("context: " + context);
EClass refContainer = (EClass) reference.eContainer();
System.err.println("ref: " + refContainer.getInstanceClassName() + "->"
+ reference.getName());
System.err.println("parent: " + parent);
System.err.println("delegate: " + delegate);
System.err.println();
}
private IScope getScopeFromReference(EReference tailReference) {
EClassifier tailType = tailReference.getEType();
IScope result = null;
if (tailType instanceof EClass) {
EClass referenceType = (EClass) tailType;
List<EReference> references = references(referenceType);
result = Scopes.scopeFor(references);
}
return result;
}
@SuppressWarnings("unchecked")
private <T extends EObject> T findParentByTypesOrdered(EObject context,
Class<?>[] parentTypeList) {
T result = null;
EObject parent = context;
while (parent.eContainer() != null) {
for (Class<?> clazz : parentTypeList) {
if (clazz.isAssignableFrom(parent.getClass())) {
result = (T) parent;
break;
}
}
if (result != null) {
break;
} else {
parent = parent.eContainer();
}
}
return result;
}
private String listContainers(EObject parentPath) {
String result = "";
EObject parent = parentPath;
while (parent.eContainer() != null) {
result = result + " " + parent.eClass().getName();
parent = parent.eContainer();
}
return result;
}
private List<EReference> references(EClass target) {
return org.eclipse.xtext.EcoreUtil2.typeSelect(
target.getEAllReferences(), EReference.class);
}
}
|
|
|
Re: no suggestions for node (xpath) [message #734138 is a reply to message #734132] |
Thu, 06 October 2011 20:10 |
|
Hi,
the "problem" is that you intoduced AxisName as a DataType rule. thus you have to care about autocompletion yourself. the generated method in the Abstract ProposalProvider is empty.
public void complete_AxisName(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// subclasses may override
}
alteratively you could change the grammar to produce a real EObject for v
AxisName:
FullAxisName | AttributeAxisName
;
AttributeAxisName:
{AttributeAxisName}'@'
;
FullAxisName:
value= ('ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self') '::'
;
~Christian
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
|
Powered by
FUDForum. Page generated in 0.03133 seconds