Scoping condition on a "local" keyword #387
-
I am new to textX (and DSL building in general) and I have a hard time getting the scoping right. I try to salvage a code that has been written by someone else about 5 years ago and which currently crashes. I try to parse a language which has global variables but that can also have local variables using the keyword LOCAL. A minimal example would look something like this: from textx.metamodel import metamodel_from_str
from textx.exceptions import TextXError
grammar = """
Program:
functions *= Function;
Function: 'FUNCTION'
locals += Locals
assignements *= Assignment
'END';
Local: name=ID;
Locals: 'LOCAL' vars*=Local[','];
Var: Local | Variable ;
Variable: name=ID;
Assignment: variable=[Var] '=' value=Number;
Number: /[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?/;
"""
try:
meta = metamodel_from_str(grammar, autokwd=True)
print("Meta-Model OK")
except TextXError as e:
print("Error in meta-model:")
print(e)
code ='''
FUNCTION
LOCAL a
a = 1
b = 2
END
FUNCTION
LOCAL a
a = 1
b = 2
END
'''
try:
model = meta.model_from_str(code)
print("Model ok")
except TextXError as e:
print("Error in model: ", e) Output:
I know that I need to use |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
You could probably solve your problem with rrel: Something Like The snippet resolves locals only. For variables you need to extend the rrel expression (add a second path to variables, separated by a comma (see example below). Note: rrel adds a scope provider for you. |
Beta Was this translation helpful? Give feedback.
-
I quickly made the demo: from textx.metamodel import metamodel_from_str
from textx.exceptions import TextXError
grammar = """
Program:
variables *= Variables
functions *= Function;
Function: 'FUNCTION'
locals += Locals
assignements *= Assignment
'END';
Local: name=ID;
Locals: 'LOCAL' vars*=Local[','];
Variables: 'VARIABLES' vars*=Variable[','];
Var: Local | Variable ;
Variable: name=ID;
Assignment: variable=[Var|ID|..~locals.vars,~variables.vars] '=' value=Number;
Number: /[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?/;
"""
try:
meta = metamodel_from_str(grammar, autokwd=True)
print("Meta-Model OK")
except TextXError as e:
print("Error in meta-model:")
print(e)
code ='''
VARIABLES b,c
FUNCTION
LOCAL a
a = 1
b = 2
c = 3
END
FUNCTION
LOCAL a
a = 1
b = 2
END
'''
def run(m):
for idx,f in enumerate(m.functions):
print(f"function no {idx}:")
for a in f.assignements:
print(f" - assignment: {a.variable.name} ({id(a.variable)}) = {a.value}")
try:
model = meta.model_from_str(code)#
print("Model ok")
run(model)
except TextXError as e:
print("Error in model: ", e) Output
|
Beta Was this translation helpful? Give feedback.
-
Thank you very much for taking the time of providing this example. It works fine and it will be useful in teaching myself how this work. However, while trying to apply it to my use cases, I ran into a few more problems. I thought it was better for me make sure that I clearly understand how rrel works. I tried to unpack the lookup tests in here https://github.com/textX/textX/blob/master/tests/functional/test_scoping/test_rrel.py For example, in this case I can relatively easily follows what is happening using the visual representation with "P2.Part2" being the sequence of names of the entities and "packages.classes" being the sequence of arrows labels on the path. Now, if I try to do something similar with the example described above, I have the visual representation where I run in a problem because the "entities" are "anonymous" (I am most certainly not using the right nomenclature, but hopefully you can understand what I mean). I tried something like |
Beta Was this translation helpful? Give feedback.
I quickly made the demo: