Commit 8bd50d6d authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Fixed scope issue when parsing procedures

parent cb4c7d10
......@@ -1791,6 +1791,7 @@ def composite_state(root, parent=None, context=None):
comp.operators = dict(context.operators)
except AttributeError:
LOG.debug('Procedure context is undefined')
inner_proc = []
# Gather the list of states defined in the composite state
# and map a list of transitionsi to each state
comp.mapping = {name: [] for name in get_state_list(root)}
......@@ -1816,7 +1817,8 @@ def composite_state(root, parent=None, context=None):
warnings.extend(warn)
comp.content.textAreas.append(textarea)
elif child.type == lexer.PROCEDURE:
new_proc, err, warn = procedure(child, context=comp)
new_proc, content, err, warn = procedure_pre(child, context=comp)
inner_proc.append((new_proc, content))
errors.extend(err)
warnings.extend(warn)
if new_proc.inputString.strip().lower() == 'entry':
......@@ -1864,6 +1866,11 @@ def composite_state(root, parent=None, context=None):
errors.extend(err)
warnings.extend(warn)
comp.content.floating_labels.append(lab)
for proc, content in inner_proc:
# parse content of procedures - all scopes are set
err, warn = procedure_post(proc, content, context=comp)
errors.extend(err)
warnings.extend(warn)
for each in states:
# And parse the states after inner states to make sure all CONNECTS
# are properly defined.
......@@ -1884,27 +1891,14 @@ def composite_state(root, parent=None, context=None):
return comp, errors, warnings
def procedure(root, parent=None, context=None):
''' Parse a procedure definition '''
proc = ogAST.Procedure()
def procedure_pre(root, parent=None, context=None):
''' Parse a procedure interface - the content has to be parsed after
all procedure interfaces are known, to prevent missing references '''
errors = []
warnings = []
# Create a list of all inherited data
try:
proc.global_variables = dict(context.variables)
proc.global_variables.update(context.global_variables)
proc.global_timers = list(context.timers)
proc.global_timers.extend(list(context.global_timers))
proc.input_signals = context.input_signals
proc.output_signals = context.output_signals
proc.procedures = context.procedures
proc.operators = dict(context.operators)
except AttributeError:
LOG.debug('Procedure context is undefined')
# Gather the list of states defined in the procedure
# and create a mapping of transitions to each state
# (Note, procedures in OG currently do NOT support states)
proc.mapping = {name: [] for name in get_state_list(root)}
proc = ogAST.Procedure()
content = []
for child in root.getChildren():
if child.type == lexer.CIF:
# Get symbol coordinates
......@@ -1920,13 +1914,6 @@ def procedure(root, parent=None, context=None):
errors.extend(err)
warnings.extend(warn)
proc.content.textAreas.append(textarea)
elif child.type == lexer.PROCEDURE:
new_proc, err, warn = procedure(child, context=proc)
errors.extend(err)
warnings.extend(warn)
proc.content.inner_procedures.append(new_proc)
# Add procedure to the context, to make it visible at scope level
context.procedures.append(new_proc)
elif child.type == lexer.EXTERNAL:
proc.external = True
elif child.type == lexer.FPAR:
......@@ -1934,27 +1921,68 @@ def procedure(root, parent=None, context=None):
errors.extend(err)
warnings.extend(warn)
proc.fpar = params
elif child.type in (lexer.PROCEDURE, lexer.START,
lexer.STATE, lexer.FLOATING_LABEL):
content.append(child)
else:
warnings.append(
'Unsupported construct in procedure, type: ' +
str(child.type) + ' - line ' + str(child.getLine()) +
' - string: ' + str(proc.inputString))
return proc, content, errors, warnings
def procedure_post(proc, content, parent=None, context=None):
''' Parse the content of a procedure '''
errors = []
warnings = []
# Create a list of all inherited data
try:
proc.global_variables = dict(context.variables)
proc.global_variables.update(context.global_variables)
proc.global_timers = list(context.timers)
proc.global_timers.extend(list(context.global_timers))
proc.input_signals = context.input_signals
proc.output_signals = context.output_signals
proc.procedures = context.procedures
proc.operators = dict(context.operators)
except AttributeError:
LOG.debug('Procedure context is undefined')
# Gather the list of states defined in the procedure
# and create a mapping of transitions to each state
# (Note, procedures in OG currently do NOT support states)
# proc.mapping = {name: [] for name in get_state_list(root)}
inner_proc = []
for child in content:
if child.type == lexer.PROCEDURE:
new_proc, content, err, warn = procedure_pre(child, context=proc)
inner_proc.append((new_proc, content))
errors.extend(err)
warnings.extend(warn)
proc.content.inner_procedures.append(new_proc)
# Add procedure to the context, to make it visible at scope level
context.procedures.append(new_proc)
elif child.type == lexer.START:
# START transition (fills the mapping structure)
proc.content.start, err, warn = start(child, context=proc)
errors.extend(err)
warnings.extend(warn)
elif child.type == lexer.STATE:
# STATE - fills up the 'mapping' structure.
newstate, err, warn = state(child, parent=None, context=proc)
errors.extend(err)
warnings.extend(warn)
proc.content.states.append(newstate)
# elif child.type == lexer.STATE:
# # STATE - fills up the 'mapping' structure.
# newstate, err, warn = state(child, parent=None, context=proc)
# errors.extend(err)
# warnings.extend(warn)
# proc.content.states.append(newstate)
elif child.type == lexer.FLOATING_LABEL:
lab, err, warn = floating_label(child, parent=None, context=proc)
errors.extend(err)
warnings.extend(warn)
proc.content.floating_labels.append(lab)
else:
warnings.append(
'Unsupported construct in procedure, type: ' +
str(child.type) + ' - line ' + str(child.getLine()) +
' - string: ' + str(proc.inputString))
for new_proc, content in inner_proc:
# parse content of procedures
err, warn = procedure_post(new_proc, content, context=proc)
errors.extend(err)
warnings.extend(warn)
for each in proc.terminators:
# check that RETURN statements type is correct
if not proc.return_type and each.return_expr:
......@@ -1978,6 +2006,17 @@ def procedure(root, parent=None, context=None):
continue
for each in chain(errors, warnings):
each[2].insert(0, 'PROCEDURE {}'.format(proc.inputString))
return errors, warnings
def procedure(root, parent=None, context=None):
''' Parse a procedure - call sequentially the pre- and post- functions
This function is called by the syntax checker only '''
proc, content, errors, warnings = procedure_pre(root, parent, context)
err, warn = procedure_post(proc, content, parent, context)
errors.extend(err)
warnings.extend(warn)
return proc, errors, warnings
......@@ -2369,6 +2408,7 @@ def process_definition(root, parent=None, context=None):
process.filename = node_filename(root)
process.parent = parent
proc_x, proc_y = 0, 0
inner_proc = []
# Prepare the transition/state mapping
process.mapping = {name: [] for name in get_state_list(root)}
for child in root.getChildren():
......@@ -2417,8 +2457,9 @@ def process_definition(root, parent=None, context=None):
# Number of instances - discarded (working on a single process)
pass
elif child.type == lexer.PROCEDURE:
proc, err, warn = procedure(
proc, content, err, warn = procedure_pre(
child, parent=None, context=process)
inner_proc.append((proc, content))
errors.extend(err)
warnings.extend(warn)
process.content.inner_procedures.append(proc)
......@@ -2445,6 +2486,10 @@ def process_definition(root, parent=None, context=None):
warnings.append('Unsupported process definition child: ' +
sdl92Parser.tokenNames[child.type] +
' - line ' + str(child.getLine()))
for proc, content in inner_proc:
err, warn = procedure_post(proc, content, context=process)
errors.extend(err)
warnings.extend(warn)
for each in chain(errors, warnings):
each[2].insert(0, 'PROCESS {}'.format(process.processName))
errors.extend(perr)
......
all: test-ada
edit:
../../../opengeode.py challenge.pr system_structure.pr
test-parse:
../../../opengeode.py challenge.pr system_structure.pr --check
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment