Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » How to get parent scope for nested block?
How to get parent scope for nested block? [message #1853811] Mon, 18 July 2022 23:42 Go to next message
Mykola Makhin is currently offline Mykola MakhinFriend
Messages: 50
Registered: July 2018
Member
If I have a DSL that allows me to declare variables in nested blocks, e.g. something like this:
blockA{var a:
 $a // reference to var a
 blockB{var b: 
  $a or $b // reference to var a and var b
   blockC{var c:
     $a or $b or $c // ref to a,b,c but not d
   }
   blockD {var d:
     $a or $b or$d // ref to a,b,d but not c
   }
 }
}


How do I make such a scope provider?
If I do something like this:
	@Override
	public IScope getScope(EObject context, EReference reference) {
		if (context instanceof ListElementReference) {
			ListElementReference listElemRef = (ListElementReference) context;
			ListFunction container = EcoreUtil2.getContainerOfType(listElemRef, ListFunction.class);
			return container != null ? Scopes.scopeFor(Arrays.asList(container.getAlias())) : IScope.NULLSCOPE;
		} else {
			return super.getScope(context, reference);
		}
	}

I get scope for each individual block, but that's it - can't reference var in parent block.

In order to do that - I somehow need to get a reference to that parent block's scope. Is there a utility to look up existing scopes for eElement?

Just in case, full grammar:
grammar x.mvmn.permock.dsl.Dsl hidden(WS, ML_COMMENT, SL_COMMENT)

generate dsl "http://www.mvmn.x/permock/dsl/Dsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore

Rule:
	'if' conditions=Condition
	('proxy' proxy=ProxyConf | 'respond' 'with' response=ResponseConf)?;

ProxyConf:
	'url' proxyUrl=STRING;

ResponseConf:
	('status' httpStatus?=INTEGER)? &
	('content' content?=STRING)? & ('headers' headers=Headers?)?;

Headers:
	headers+=Header (',' headers+=Header)*;

Header:
	headerName=STRING ':' headerValue=STRING;

Condition:
	OrCondition;

OrCondition returns Condition:
	AndCondition ({OrCondition.left=current} 'or' right=AndCondition)*;

AndCondition returns Condition:
	OptionalNegationCondition ({AndCondition.left=current} 'and' right=OptionalNegationCondition)*;

OptionalNegationCondition returns Condition:
	BracketedCondition | {Negation} 'not' negated=BracketedCondition;

BracketedCondition returns Condition:
	expression=Expression | '(' condition=Condition ')';

Expression:
	left=Operand (op=Operator right=Operand)?;

Operand:
	ref=Reference | const=Constant | listElementRef=ListElementReference;

ListFunction:
	'{' op=ListOperation alias=ListElementAlias separator=':' condition=Condition '}';

ListElementAlias:
	name=ID;

Reference hidden(WS):
	name=Entity (prop=PropertyRef)?;

ListElementReference hidden(WS):
	'$' name=[ListElementAlias|ID] (prop=PropertyRef)?;

PropertyRef hidden(WS):
	('.' name=ID | '[' (name=STRING | index=INTEGER) ']' | listFunc=ListFunction)
	(subPropery=PropertyRef)?;

enum Operator:
	EQ='=' | NEQ='!=' | GT='>' | GTEQ='>=' | LT='<' | LTEQ='<=' | REGEX='~=';

Constant:
	strVal=STRING | intVal=INTEGER | floatVal=FLOAT;

enum ListOperation:
	FILTER='where' | ALL='all' | ANY='any';

Entity:
	name=ID;

terminal FLOAT returns ecore::EDoubleObject:
	INTEGER '.' INTEGER;

terminal INTEGER returns ecore::EIntegerObject:
	('0'..'9')+;

terminal ID:
	'^'? ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;

terminal STRING:
	'"' ('\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\' | '"'))* '"' |
	"'" ('\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\' | "'"))* "'";

terminal ML_COMMENT:
	'/*'->'*/';

terminal SL_COMMENT:
	'//' !('\n' | '\r')* ('\r'? '\n')?;

terminal WS:
	(' ' | '\t' | '\r' | '\n')+;

terminal ANY_OTHER:
	.;


Sample code
if
	a{
			all a:
		$a or b{
				all b:
			$a or $b or c{
					all c:
				$a or $b or $c
			} or d{
					all d:
				$a or $b or $d
			}
		}
	}

[Updated on: Mon, 18 July 2022 23:55]

Report message to a moderator

Re: How to get parent scope for nested block? [message #1853812 is a reply to message #1853811] Tue, 19 July 2022 00:13 Go to previous messageGo to next message
Mykola Makhin is currently offline Mykola MakhinFriend
Messages: 50
Registered: July 2018
Member
P.S. Using this solution for now:


public class DslScopeProvider extends AbstractDslScopeProvider {

	@Inject
	IResourceScopeCache scopeCache;

	@Override
	public IScope getScope(EObject context, EReference reference) {
		if (context instanceof ListElementReference) {
			ListElementReference listElemRef = (ListElementReference) context;
			ListFunction container = EcoreUtil2.getContainerOfType(listElemRef, ListFunction.class);
			return container != null && container.getAlias() != null
					? Scopes.scopeFor(Arrays.asList(container.getAlias()), getParentScope(container))
					: getParentScope(container);
		} else {
			return super.getScope(context, reference);
		}
	}

	protected IScope getParentScope(ListFunction container) {
		IScope result = IScope.NULLSCOPE;
		if (container != null) {
			ListFunction parentContainer = EcoreUtil2.getContainerOfType(container.eContainer(), ListFunction.class);
			if (parentContainer != null) {
				String path = EcoreUtil2.getFragmentPath(parentContainer.getAlias());
				System.out.println(path);
				result = scopeCache.get(path, container.eResource(), () -> Scopes
						.scopeFor(Arrays.asList(parentContainer.getAlias()), getParentScope(parentContainer)));
			}
		}
		return result;
	}
}
Re: How to get parent scope for nested block? [message #1853908 is a reply to message #1853812] Fri, 22 July 2022 06:36 Go to previous message
Rubén Porras Campo is currently offline Rubén Porras CampoFriend
Messages: 67
Registered: July 2009
Member
Hi Mykola,

I am not sure if there are better ways, but your approach seems reasonable to me. I am sorry that I not have time to dig into our product to see how we exactly deal with the problem.

Regards.
Previous Topic:Xtext & Xtend Release 2.27.0 is available now
Next Topic:Xtext error when used as a tool plugin
Goto Forum:
  


Current Time: Fri May 10 21:43:29 GMT 2024

Powered by FUDForum. Page generated in 0.03488 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top