Просмотр исходного кода

Getting closer to XML parsing nirvana...

Joeri Exelmans 5 лет назад
Родитель
Сommit
10288e3385
73 измененных файлов с 1388 добавлено и 1425 удалено
  1. 4 4
      src/sccd/controller/controller.py
  2. 3 0
      src/sccd/execution/statechart_instance.py
  3. 5 2
      src/sccd/parser/expression_parser.py
  4. 412 437
      src/sccd/parser/statechart_parser.py
  5. 4 6
      src/sccd/syntax/statechart.py
  6. 1 1
      src/sccd/syntax/statement.py
  7. 23 5
      src/sccd/syntax/tree.py
  8. 3 5
      test/lib/test.py
  9. 72 102
      test/lib/test_parser.py
  10. 10 10
      test/render.py
  11. 4 4
      test/test_files/day_atlee/fail_02_counter_takemany.xml
  12. 39 39
      test/test_files/day_atlee/statechart_fig1_redialer.svg
  13. 53 55
      test/test_files/day_atlee/statechart_fig1_redialer.xml
  14. 4 4
      test/test_files/day_atlee/statechart_fig7_dialer.svg
  15. 9 12
      test/test_files/day_atlee/statechart_fig7_dialer.xml
  16. 41 41
      test/test_files/day_atlee/statechart_fig8_counter.svg
  17. 22 24
      test/test_files/day_atlee/statechart_fig8_counter.xml
  18. 1 2
      test/test_files/day_atlee/test_01_dialer_takemany.xml
  19. 1 2
      test/test_files/day_atlee/test_01_dialer_takeone.xml
  20. 4 4
      test/test_files/day_atlee/test_02_counter_takeone.xml
  21. 4 4
      test/test_files/day_atlee/test_06_counter_lifeline.xml
  22. 1 1
      test/test_files/day_atlee/test_07_redialer_same.xml
  23. 6 8
      test/test_files/features/after/fail_duration_type.xml
  24. 21 23
      test/test_files/features/after/test_after.xml
  25. 25 27
      test/test_files/features/after/test_after_reentry.xml
  26. 9 11
      test/test_files/features/datamodel/fail_static_types.xml
  27. 1 3
      test/test_files/features/datamodel/fail_unique_var.xml
  28. 8 10
      test/test_files/features/datamodel/test_cond.xml
  29. 4 4
      test/test_files/features/datamodel/test_guard_action.svg
  30. 13 15
      test/test_files/features/datamodel/test_guard_action.xml
  31. 65 67
      test/test_files/features/expressions/test_expressions.xml
  32. 69 71
      test/test_files/features/expressions/test_expressions_ortho.xml
  33. 9 11
      test/test_files/features/functions/fail_parameter_type.xml
  34. 9 11
      test/test_files/features/functions/fail_return_type.xml
  35. 46 0
      test/test_files/features/functions/test_functions.svg
  36. 10 12
      test/test_files/features/functions/test_functions.xml
  37. 1 1
      test/test_files/semantics/big_step_maximality/statechart_flat.svg
  38. 15 17
      test/test_files/semantics/big_step_maximality/statechart_flat.xml
  39. 1 1
      test/test_files/semantics/big_step_maximality/statechart_ortho.svg
  40. 34 36
      test/test_files/semantics/big_step_maximality/statechart_ortho.xml
  41. 23 25
      test/test_files/semantics/big_step_maximality/test_flat_syntactic.xml
  42. 1 1
      test/test_files/semantics/big_step_maximality/test_flat_takemany.xml
  43. 1 1
      test/test_files/semantics/big_step_maximality/test_flat_takeone.xml
  44. 71 71
      test/test_files/semantics/big_step_maximality/test_ortho_syntactic.svg
  45. 62 51
      test/test_files/semantics/big_step_maximality/test_ortho_syntactic.xml
  46. 1 1
      test/test_files/semantics/big_step_maximality/test_ortho_takemany.xml
  47. 1 1
      test/test_files/semantics/big_step_maximality/test_ortho_takeone.xml
  48. 1 1
      test/test_files/semantics/event_lifeline/statechart_flat.svg
  49. 17 19
      test/test_files/semantics/event_lifeline/statechart_flat.xml
  50. 1 1
      test/test_files/semantics/event_lifeline/statechart_ortho.svg
  51. 30 32
      test/test_files/semantics/event_lifeline/statechart_ortho.xml
  52. 1 1
      test/test_files/semantics/event_lifeline/test_flat_nextbs.xml
  53. 1 1
      test/test_files/semantics/event_lifeline/test_flat_nextss_takemany.xml
  54. 1 1
      test/test_files/semantics/event_lifeline/test_flat_nextss_takeone.xml
  55. 1 1
      test/test_files/semantics/event_lifeline/test_ortho_nextbs.xml
  56. 1 1
      test/test_files/semantics/event_lifeline/test_ortho_nextcs_takemany.xml
  57. 1 1
      test/test_files/semantics/event_lifeline/test_ortho_nextcs_takeone.xml
  58. 1 1
      test/test_files/semantics/event_lifeline/test_ortho_nextss.xml
  59. 17 19
      test/test_files/semantics/memory_protocol/fail_race_condition.xml
  60. 25 25
      test/test_files/semantics/memory_protocol/statechart_enabledness.svg
  61. 20 22
      test/test_files/semantics/memory_protocol/statechart_enabledness.xml
  62. 6 6
      test/test_files/semantics/memory_protocol/test_gcbig.xml
  63. 1 1
      test/test_files/semantics/memory_protocol/test_gccombo.xml
  64. 1 1
      test/test_files/semantics/memory_protocol/test_gcsmall.xml
  65. 4 6
      test/test_files/syntax/fail_after_and_event.xml
  66. 3 5
      test/test_files/syntax/fail_no_id.xml
  67. 4 6
      test/test_files/syntax/fail_missing_initial.xml
  68. 2 2
      test/test_files/syntax/fail_missing_root.xml
  69. 4 6
      test/test_files/syntax/fail_missing_target.xml
  70. 7 5
      test/test_files/syntax/fail_multiple_root.xml
  71. 4 6
      test/test_files/syntax/fail_root_transition.xml
  72. 4 6
      test/test_files/syntax/fail_sibling_id.xml
  73. 4 6
      test/test_files/syntax/fail_wrong_initial.xml

+ 4 - 4
src/sccd/controller/controller.py

@@ -44,10 +44,10 @@ class Controller:
             if input.name == "":
                 raise Exception("Input event can't have an empty name.")
         
-            try:
-                self.model.globals.inports.get_id(input.port)
-            except KeyError as e:
-                raise Exception("No such port: '%s'" % input.port) from e
+            # try:
+            #     self.model.globals.inports.get_id(input.port)
+            # except KeyError as e:
+            #     raise Exception("No such port: '%s'" % input.port) from e
 
             try:
                 event_id = self.model.globals.events.get_id(input.name)

+ 3 - 0
src/sccd/execution/statechart_instance.py

@@ -19,6 +19,9 @@ class StatechartInstance(Instance):
 
         semantics = statechart.semantics
 
+        if isinstance(semantics, VariableSemantics):
+            raise Exception("Cannot execute model with variable semantics.")
+
         reverse = semantics.priority == Priority.SOURCE_CHILD
 
         generator = CandidatesGeneratorCurrentConfigBased(reverse)

+ 5 - 2
src/sccd/parser/expression_parser.py

@@ -100,7 +100,9 @@ class _ExpressionTransformer(Transformer):
     return (pos_events, neg_events)
 
   def event_decl(self, node):
-    return EventDecl(name=node[0], params=node[1])
+    event_name = node[0]
+    event_id = self.globals.events.assign_id(event_name)
+    return EventDecl(id=event_id, name=event_name, params=node[1])
 
   params_decl = list
 
@@ -134,7 +136,8 @@ def parse_block(globals: Globals, text: str) -> Statement:
   _transformer.globals = globals
   return _parser.parse(text, start="block")
 
-def parse_events_decl(text: str):
+def parse_events_decl(globals: Globals, text: str):
+  _transformer.globals = globals
   return _parser.parse(text, start="event_decl_list")
 
 def parse_func_decl(text: str) -> Tuple[str, List[Param]]:

+ 412 - 437
src/sccd/parser/statechart_parser.py

@@ -1,16 +1,21 @@
-import dataclasses
+from typing import *
 from lxml import etree
-from sccd.parser.expression_parser import *
 from sccd.syntax.statechart import *
 from sccd.syntax.tree import *
-from sccd.execution.event import *
 from sccd.execution import builtin_scope
+from sccd.parser.expression_parser import *
 
-_blank_eval_context = EvalContext(current_state=None, events=[], memory=None)
+class XmlError(Exception):
+  pass
+
+class XmlErrorElement(Exception):
+  def __init__(self, el: etree.Element, msg):
+    super().__init__(msg)
+    self.el = el
 
 # An Exception that occured while visiting an XML element.
 # It will show a fragment of the source file and the line number of the error.
-class XmlLoadError(Exception):
+class XmlDecoratedError(Exception):
   def __init__(self, src_file: str, el: etree.Element, msg):
     # This is really dirty, but can't find a clean way to do this with lxml.
 
@@ -52,442 +57,412 @@ class XmlLoadError(Exception):
     # self.el = el
     # self.err = err
 
-
-class XmlParser:
-
-  # Stack-like data structure extensively used for event-driven parsing.
-  # Typically, when visiting the opening tag of a parent XML element, a context value is *pushed*, and when visiting the matching closing tag, that value is popped. Child XML elements will be able to "peek" or, more often, "require" a context value to "be there". This way, child XML elements can express only being allowed as children of certain parent XML elements that push/pop these contexts, otherwise raising an exception.
-  class Context:
-    def __init__(self, name):
-      self.data = []
-      self.name = name
-
-    def push(self, value):
-      self.data.append(value)
-
-    def pop(self):
-      return self.data.pop()
-
-    def peek(self, default=None):
-      try:
-        return self.data[-1]
-      except IndexError:
-        return default
-
-    # Same as peek, but raises exception of stack is empty
-    def require(self):
-      try:
-        return self.data[-1]
-      except IndexError as e:
-        raise Exception("Element expected only within context: %s" % self.name) from e
-
-
-  def __init__(self):
-    self.src_file = XmlParser.Context("src_file")
-
-  def parse(self, src_file):
-    self.src_file.push(src_file)
-
-    for event, el in etree.iterparse(src_file, events=("start", "end")):
-      # print(event, el.tag)
-      try:
-        if event == "start":
-          start_method = getattr(self, "start_"+el.tag, None)
-          if start_method:
-            start_method(el)
-
-        elif event == "end":
-          end_method = getattr(self, "end_"+el.tag, None)
-          if end_method:
-            end_method(el)
-
-      except XmlLoadError:
-        raise
-      except Exception as e:
-        # An advantage of this event-driven parsing is that if an exception is thrown during the visiting of an XML node, we can automatically decorate it with info about the tag where the error occured, the line number in the source file, etc.
-        self._raise(el, str(e), e)
-
-      # We don't need anything from this element anymore, so we clear it to save memory.
-      # This is a technique mentioned in the lxml documentation:
-      # https://lxml.de/tutorial.html#event-driven-parsing
-      # el.clear()
-      # Currently disabled for 2 reasons:
-      # 1) Because we store <transition> elements and need to read their attributes later on.
-      # 2) To be able to pretty-print XML data later on, if a future error occurs.
-      
-    self.src_file.pop()
-
-  def _raise(self, el, msg, err: Exception):
-    src_file = self.src_file.require()
-    raise XmlLoadError(src_file, el, msg) from err
-
-
-# Parses action elements: <raise>, <code>
-class ActionParser(XmlParser):
-
-  def __init__(self):
-    super().__init__()
-    self.globals = XmlParser.Context("globals")
-    self.scope = XmlParser.Context("scope")
-    self.actions = XmlParser.Context("actions")
-
-  def end_raise(self, el):
-    globals = self.globals.require()
-    actions = self.actions.require()
-
-    name = el.get("event")
-    port = el.get("port")
-    if not port:
-      # internal event
-      event_id = globals.events.assign_id(name)
-      a = RaiseInternalEvent(name=name, parameters=[], event_id=event_id)
-    else:
-      # output event - no ID in global namespace
-      globals.outports.assign_id(port)
-      a = RaiseOutputEvent(name=name, parameters=[], outport=port, time_offset=0)
-    actions.append(a)
-
-  def end_code(self, el):
-    globals = self.globals.require()
-    scope = self.scope.require()
-    actions = self.actions.require()
-
-    block = parse_block(globals, el.text)
-    block.init_stmt(scope)
-    a = Code(block)
-    actions.append(a)
-
-# Parses state elements: <state>, <parallel>, <history>,
-# and all its children (transitions, entry/exit actions)
-class StateParser(ActionParser):
-
-  def __init__(self):
-    super().__init__()
-    self.state = XmlParser.Context("state")
-    self.state_children = XmlParser.Context("state_children")
-    self.transitions = XmlParser.Context("transitions")
-
-  def _internal_start_state(self, el, constructor):
-    parent = self.state.peek(default=None)
-
-    short_name = el.get("id", "")
-    if parent is None:
-      if short_name:
-        raise Exception("Root <state> must not have 'id' attribute.")
-    else:
-      if not short_name:
-        raise Exception("Non-root <state> must have 'id' attribute.")
-
-    state = constructor(short_name, parent)
-
-    parent_children = self.state_children.require()
-    already_there = parent_children.setdefault(short_name, state)
-    if already_there is not state:
-      if parent:
-        raise Exception("Sibling state with the same id exists.")
+ParseElementF = Callable[[etree.Element], Optional['Parser']]
+OrderedElements = List[Tuple[str, ParseElementF]]
+UnorderedElements = Dict[str, ParseElementF]
+Parser = Union[OrderedElements, UnorderedElements]
+ParserWDone = Union[Parser, Tuple[Parser,Callable]]
+
+def parse(src_file, rules: ParserWDone, ignore_unmatched = False, disable_multiplicities = False):
+
+  class Multiplicity(Flag):
+    AT_LEAST_ONCE = auto()
+    AT_MOST_ONCE = auto()
+
+    ANY = 0
+    ONCE = AT_LEAST_ONCE | AT_MOST_ONCE
+    OPTIONAL = AT_MOST_ONCE
+    MULTIPLE = AT_LEAST_ONCE
+
+    @staticmethod
+    def parse_suffix(tag: str) -> Tuple[str, 'Multiplicity']:
+      if tag.endswith("*"):
+        m = Multiplicity.ANY
+        tag = tag[:-1]
+      elif tag.endswith("?"):
+        m = Multiplicity.OPTIONAL
+        tag = tag[:-1]
+      elif tag.endswith("+"):
+        m = Multiplicity.MULTIPLE
+        tag = tag[:-1]
       else:
-        raise Exception("Only 1 root <state> allowed.")
-
-    if el.get("stable", "") == "true":
-      state.stable = True
-
-    self.state.push(state)
-    self.state_children.push({})
-
-  def _internal_end_state(self):
-    state_children = self.state_children.pop()
-    state = self.state.pop()
-    return (state, state_children)
-
-  def start_state(self, el):
-    self._internal_start_state(el, State)
-
-  def end_state(self, el):
-    state, state_children = self._internal_end_state()
-
-    initial = el.get("initial", None)
-    if initial is not None:
-      try:
-        state.default_state = state_children[initial]
-      except KeyError as e:
-        raise Exception("initial=\"%s\": not a child." % (initial)) from e
-    elif len(state.children) == 1:
-      state.default_state = state.children[0]
-    elif len(state.children) > 1:
-      raise Exception("More than 1 child state: must set 'initial' attribute.")
-
-  def start_parallel(self, el):
-    self._internal_start_state(el, ParallelState)
-
-  def end_parallel(self, el):
-    self._internal_end_state()
-
-  def start_history(self, el):
-    if el.get("type", "shallow") == "deep":
-      self._internal_start_state(el, DeepHistoryState)
-    else:
-      self._internal_start_state(el, ShallowHistoryState)
-
-  def end_history(self, el):
-    return self._internal_end_state()
-
-  def start_onentry(self, el):
-    self.actions.push([])
-
-  def end_onentry(self, el):
-    actions = self.actions.pop()
-    self.state.require().enter = actions
-
-  def start_onexit(self, el):
-    self.actions.push([])
-
-  def end_onexit(self, el):
-    actions = self.actions.pop()
-    self.state.require().exit = actions
-
-  def start_transition(self, el):
-    parent_scope = self.scope.require()
-    globals = self.globals.require()
-    if self.state.require().parent is None:
-      raise Exception("Root <state> cannot be source of a transition.")
-
-    scope = Scope("transition", parent=parent_scope)
-
-    event = el.get("event")
-
-    if event is not None:
-      positive_events, negative_events = parse_events_decl(event)
+        m = Multiplicity.ONCE
+      return tag, m
+
+    def unparse_suffix(self, tag: str) -> str:
+      return tag + {
+        Multiplicity.ANY: "*",
+        Multiplicity.ONCE: "",
+        Multiplicity.OPTIONAL: "?",
+        Multiplicity.MULTIPLE: "+"
+      }[self]
+
+  rules_stack = [rules]
+  results_stack = [[]]
+
+  for event, el in etree.iterparse(src_file, events=("start", "end")):
+    try:
+      if event == "start":
+        # print("start", el.tag)
+        allowed_tags = []
+        when_done = None
+        pair = rules_stack[-1]
+        if isinstance(pair, tuple):
+          rules, when_done = pair
+        else:
+          rules = pair
+
+        parse_function = None
+        if isinstance(rules, dict):
+          # print("rules:", list(rules.keys()))
+          try:
+            parse_function = rules[el.tag]
+          except KeyError as e:
+            pass
+
+        elif isinstance(rules, list):
+          # print("rules:", [rule[0] for rule in rules])
+          # Expecting elements in certain order and with certain multiplicities
+          while len(rules) > 0:
+            tag_w_suffix, func = rules[0]
+            tag, m = Multiplicity.parse_suffix(tag_w_suffix)
+            if tag == el.tag:
+              if m & Multiplicity.AT_MOST_ONCE:
+                # We don't allow this element next time
+                rules = rules[1:]
+                rules_stack[-1] = (rules, when_done)
+
+              elif m & Multiplicity.AT_LEAST_ONCE:
+                # We don't require this element next time
+                m &= ~Multiplicity.AT_LEAST_ONCE
+                rules = list(rules) # copy list before editing
+                rules[0] = (m.unparse_suffix(tag), func) # edit rule
+                rules_stack[-1] = (rules, when_done)
+
+              parse_function = func
+              break
+            else:
+              if not disable_multiplicities and m & Multiplicity.AT_LEAST_ONCE:
+                raise XmlError("Expected required element <%s>" % tag)
+              else:
+                # Element is skipable
+                rules = rules[1:]
+                rules_stack[-1] = (rules, when_done)
+        else:
+          assert False # rule should always be a dict or list
+
+        if parse_function:
+          children_rules = parse_function(el)
+          if children_rules:
+            rules_stack.append(children_rules)
+          else:
+            rules_stack.append([])
+        else:
+          if not ignore_unmatched:
+            raise XmlError("Unexpected element.")
+          else:
+            rules_stack.append([])
+        results_stack.append([])
+
+      elif event == "end":
+        children_results = results_stack.pop()
+        when_done = None
+        pair = rules_stack.pop()
+        if isinstance(pair, tuple):
+          rules, when_done = pair
+        else:
+          rules = pair
+
+        if when_done:
+          result = when_done(*children_results)
+          # print("end", el.tag, "with result=", result)
+          if result:
+            results_stack[-1].append(result)
+        # else:
+        #   print("end", el.tag)
+
+
+
+    except XmlError as e:
+      raise XmlDecoratedError(src_file, el, str(e)) from e
+    except XmlErrorElement as e:
+      raise XmlDecoratedError(src_file, e.el, str(e)) from e
+
+  results = results_stack[0] # sole stack frame remaining
+  if len(results) > 0:
+    return results[0] # return first item, since we expect at most one item since an XML file has only one root node
+
+class SkipFile(Exception):
+  pass
 
-      positive_bitmap = Bitmap()
-      negative_bitmap = Bitmap()
-
-      def process_event_decl(e: EventDecl):
-        for i,p in enumerate(e.params):
-          scope.add_event_parameter(event_name=e.name, param_name=p.name, type=p.type, param_offset=i)
-
-      for e in positive_events:
-        event_id = globals.events.assign_id(e.name)
-        positive_bitmap |= bit(event_id)
-        process_event_decl(e)
-
-      for e in negative_events:
-        event_id = globals.events.assign_id(e.name)
-        negative_bitmap |= bit(event_id)
-        process_event_decl(e)
-
-      if not negative_bitmap:
-        trigger = Trigger(positive_bitmap)
-      else:
-        trigger = NegatedTrigger(positive_bitmap, negative_bitmap)
-
-    self.scope.push(scope)
-    self.actions.push([])
-
-  def end_transition(self, el):
-    transitions = self.transitions.require()
-    scope = self.scope.pop()
-    actions = self.actions.pop()
-    source = self.state.require()
-
-    # Parse <transition> element not until all states have been parsed,
-    # and state tree constructed.
-    transitions.append((el, source, actions, scope))
-
-# Parses <tree> element and all its children.
-# In practice, this can't really parse a <tree> element because any encountered expression may contain identifiers pointing to model variables declared outside the <tree> element. To parse a <tree>, either manually add those variables to the 'scope', or, more likely, use a StatechartParser instance which will do this for you while parsing the <datamodel> node.
-class TreeParser(StateParser):
-
-  def __init__(self):
-    super().__init__()
-    self.statechart = XmlParser.Context("statechart")
-
-  # <tree>
-
-  def start_tree(self, el):
-    statechart = self.statechart.require()
-    self.scope.push(statechart.scope)
-    self.transitions.push([])
-    self.state_children.push({})
-
-  def end_tree(self, el):
-    statechart = self.statechart.require()
-    globals = self.globals.require()
-    scope = self.scope.pop()
-
-    root_states = self.state_children.pop()
-    if len(root_states) == 0:
-      raise Exception("Missing root <state> !")
-    root = list(root_states.values())[0]
-
-    # Add transitions.
-    # Only now that our tree structure is complete can we resolve 'target' states of transitions.
-    next_after_id = 0
-    transitions = self.transitions.pop()
-    for t_el, source, actions, t_scope in transitions:
-      target_string = t_el.get("target")
-      event = t_el.get("event")
-      port = t_el.get("port")
-      after = t_el.get("after")
-      cond = t_el.get("cond")
-
-      if target_string is None:
-        self._raise(t_el, "Missing mandatory attribute: 'target'.", None)
-
-      try:
-        # Parse and find target state
-        parse_tree = parse_state_ref(target_string)
-      except Exception as e:
-        self._raise(t_el, "Parsing target '%s': %s" % (target_string, str(e)), e)
-
-      def find_state(sequence) -> State:
-        if sequence.data == "relative_path":
-          state = source
-        elif sequence.data == "absolute_path":
-          state = root
-        for item in sequence.children:
-          if item.type == "PARENT_NODE":
-            state = state.parent
-          elif item.type == "CURRENT_NODE":
-            continue
-          elif item.type == "IDENTIFIER":
-            state = [x for x in state.children if x.short_name == item.value][0]
-        return state
-
-      try:
-        targets = [find_state(seq) for seq in parse_tree.children]
-      except Exception as e:
-        self._raise(t_el, "Could not find target '%s'." % (target_string), e)
-
-      transition = Transition(source, targets)
-
-      # Trigger
-      if after is not None:
-        if event is not None:
-          self._raise(t_el, "Can only specify one of attributes 'after', 'event'.", None)
-        try:
-          after_expr = parse_expression(globals, after)
-          after_type = after_expr.init_rvalue(t_scope)
-          if after_type != Duration:
-            msg = "Expression is '%s' type. Expected 'Duration' type." % str(after_type)
-            if after_type == int:
-              msg += "\n Hint: Did you forget a duration unit sufix? ('s', 'ms', ...)"
-            raise Exception(msg)
-          event = "_after%d" % next_after_id # transition gets unique event name
-          trigger = AfterTrigger(globals.events.assign_id(event), event, next_after_id, after_expr)
-          next_after_id += 1
-        except Exception as e:
-          self._raise(t_el, "after=\"%s\": %s" % (after, str(e)), e)
-      elif event is not None:
-        event_id = globals.events.assign_id(event)
-        trigger = EventTrigger(event_id, event, port)
-        globals.inports.assign_id(port)
-      else:
-        trigger = None
-      transition.trigger = trigger
-      # Actions
-      transition.actions = actions
-      # Guard
-      if cond is not None:
-        try:
-          expr = parse_expression(globals, cond)
-          expr.init_rvalue(t_scope)
-        except Exception as e:
-          self._raise(t_el, "cond=\"%s\": %s" % (cond, str(e)), e)
-        transition.guard = expr
-      source.transitions.append(transition)
-
-    statechart.tree = StateTree(root)
-
-# Parses <statechart> element and all its children.
-class StatechartParser(TreeParser):
-
-  def __init__(self, load_external = True):
-    super().__init__()
-    self.load_external = load_external
-
-    self.statecharts = XmlParser.Context("statecharts")
-
-  # <semantics>
-
-  def _internal_end_semantics(self, el):
-    statechart = self.statechart.require()
-    # Use reflection to find the possible XML attributes and their values
-    for aspect in dataclasses.fields(Semantics):
-      text = el.get(aspect.name)
-      if text is not None:
-        result = parse_semantic_choice(text)
-        if result.data == "wildcard":
-          setattr(statechart.semantics, aspect.name, list(aspect.type))
-        elif result.data == "list":
-          options = [aspect.type[token.value.upper()] for token in result.children]
-          setattr(statechart.semantics, aspect.name, options)
-
-  def end_semantics(self, el):
-    self._internal_end_semantics(el)
-
-  def end_override_semantics(self, el):
-    if self.load_external:
-      self._internal_end_semantics(el)
-
-  # <datamodel>
-
-  def end_var(self, el):
-    globals = self.globals.require()
-    scope = self.scope.require()
-
-    id = el.get("id")
-    expr = el.get("expr")
-
-    parsed = parse_expression(globals, expr)
-    rhs_type = parsed.init_rvalue(scope)
-    val = parsed.eval(_blank_eval_context)
-    scope.add_variable_w_initial(name=id, initial=val)
-
-  def end_func(self, el):
-    globals = self.globals.require()
-    scope = self.scope.require()
-
-    id = el.get("id")
-    text = el.text
-
-    name, params = parse_func_decl(id)
-
-    # print("name:", name)
-    # print("params:", params)
-
-    body = parse_block(globals, text)
-    func = Function(params, body)
-    func.init_stmt(scope)
-
-    scope.add_function(name, func)
-
-  def start_datamodel(self, el):
-    statechart = self.statechart.require()
-    self.scope.push(statechart.scope)
-
-  def end_datamodel(self, el):
-    self.scope.pop()
+_blank_eval_context = EvalContext(current_state=None, events=[], memory=None)
 
-  # <statechart>
+def require_attribute(el, attr):
+  val = el.get(attr)
+  if val is None:
+    raise XmlError("missing required attribute '%s'" % attr)
+  return val
 
-  def start_statechart(self, el):
-    src_file = self.src_file.require()
+def create_statechart_parser(globals, src_file, load_external = True):
+  def parse_statechart(el):
     ext_file = el.get("src")
-    statechart = None
     if ext_file is None:
-      statechart = StatechartVariableSemantics(tree=None, semantics=VariableSemantics(), scope=Scope("instance", parent=builtin_scope.builtin_scope))
-    elif self.load_external:
+      statechart = Statechart(
+        inport_events={},
+        event_outport={},
+        semantics=VariableSemantics(),
+        tree=None,
+        scope=Scope("instance", parent=builtin_scope.builtin_scope))
+    else:
+      if not load_external:
+        raise SkipFile("Parser configured not to load statecharts from external files.")
+      import os
       ext_file_path = os.path.join(os.path.dirname(src_file), ext_file)
-      self.statecharts.push([])
-      self.parse(ext_file_path)
-      statecharts = self.statecharts.pop()
-      if len(statecharts) != 1:
-        raise Exception("Expected exactly 1 <statechart> node, got %d." % len(statecharts))
-      statechart = statecharts[0]
-    self.statechart.push(statechart)
-
-  def end_statechart(self, el):
-    statecharts = self.statecharts.require()
-    sc = self.statechart.pop()
-    if sc is not None:
-      statecharts.append(sc)
+      statechart = parse(ext_file_path, create_statechart_parser(globals, ext_file_path))
+
+    def parse_semantics(el):
+      import dataclasses
+      # Use reflection to find the possible XML attributes and their values
+      for aspect in dataclasses.fields(Semantics):
+        text = el.get(aspect.name)
+        if text is not None:
+          result = parse_semantic_choice(text)
+          if result.data == "wildcard":
+            setattr(statechart.semantics, aspect.name, list(aspect.type))
+          elif result.data == "list":
+            options = [aspect.type[token.value.upper()] for token in result.children]
+            setattr(statechart.semantics, aspect.name, options)
+
+    def parse_datamodel(el):
+      def parse_var(el):
+        id = el.get("id")
+        expr = el.get("expr")
+
+        parsed = parse_expression(globals, expr)
+        rhs_type = parsed.init_rvalue(statechart.scope)
+        val = parsed.eval(_blank_eval_context)
+        statechart.scope.add_variable_w_initial(name=id, initial=val)
+
+      def parse_func(el):
+        id = el.get("id")
+        text = el.text
+
+        name, params = parse_func_decl(id)
+        body = parse_block(globals, text)
+        func = Function(params, body)
+        func.init_stmt(statechart.scope)
+        statechart.scope.add_function(name, func)
+
+      return {"var": parse_var, "func": parse_func}
+
+    def parse_inport(el):
+      port_name = require_attribute(el, "name")
+      def parse_event(el):
+        event_name = require_attribute(el, "name")
+        event_id = globals.events.assign_id(event_name)
+        port_events = statechart.inport_events.setdefault(port_name, set())
+        port_events.add(event_id)
+      return [("event+", parse_event)]
+
+    def parse_outport(el):
+      port_name = require_attribute(el, "name")
+      def parse_event(el):
+        event_name = require_attribute(el, "name")
+        statechart.event_outport[event_name] = port_name
+      return [("event+", parse_event)]
+
+    def parse_root(el):
+      root = State("", parent=None)
+      children_dict = {}
+      transitions = []
+      next_after_id = 0
+
+      def create_actions_parser(scope):
+
+        def parse_raise(el):
+          def when_done():
+            event_name = require_attribute(el, "event")
+            try:
+              port = statechart.event_outport[event_name]
+            except KeyError:
+              # Legacy fallback: read port from attribute
+              port = el.get("port")
+            if port is None:
+              # internal event
+              event_id = globals.events.assign_id(event_name)
+              return RaiseInternalEvent(name=event_name, parameters=[], event_id=event_id)
+            else:
+              # output event - no ID in global namespace
+              globals.outports.assign_id(port)
+              return RaiseOutputEvent(name=event_name, parameters=[], outport=port, time_offset=0)
+          return ([], when_done)
+
+        def parse_code(el):
+          def when_done():
+            block = parse_block(globals, el.text)
+            block.init_stmt(scope)
+            return Code(block)
+          return ([], when_done)
+
+        return {"raise": parse_raise, "code": parse_code}
+
+      def deal_with_initial(el, state, children_dict):
+        initial = el.get("initial")
+        if initial is not None:
+          try:
+            state.default_state = children_dict[initial]
+          except KeyError as e:
+            print("children:", children_dict.keys())
+            raise XmlError("initial=\"%s\": not a child." % (initial)) from e
+        elif len(state.children) == 1:
+          state.default_state = state.children[0]
+        elif len(state.children) > 1:
+          raise XmlError("More than 1 child state: must set 'initial' attribute.")
+
+      def create_state_parser(parent, sibling_dict):
+
+        def common(el, constructor):
+          short_name = require_attribute(el, "id")
+          state = constructor(short_name, parent)
+
+          already_there = sibling_dict.setdefault(short_name, state)
+          if already_there is not state:
+            raise XmlError("Sibling state with the same id exists.")
+          return state
+
+        def common_nonpseudo(el, constructor):
+          state = common(el, constructor)
+          if el.get("stable", "") == "true":
+            state.stable = True
+          return state
+
+        def parse_state(el):
+          state = common_nonpseudo(el, State)
+          children_dict = {}
+          def when_done():
+            deal_with_initial(el, state, children_dict)
+          return (create_state_parser(parent=state, sibling_dict=children_dict), when_done)
+
+        def parse_parallel(el):
+          state = common_nonpseudo(el, ParallelState)
+          return create_state_parser(parent=state, sibling_dict={})
+
+        def parse_history(el):
+          history_type = el.get("type", "shallow")
+          if history_type == "deep":
+            common(el, DeepHistoryState)
+          elif history_type == "shallow":
+            common(el, ShallowHistoryState)
+          else:
+            raise XmlError("attribute 'type' must be \"shallow\" or \"deep\".")
+
+        def parse_onentry(el):
+          def when_done(*actions):
+            parent.enter = actions
+          return (create_actions_parser(statechart.scope), when_done)
+
+        def parse_onexit(el):
+          def when_done(*actions):
+            parent.exit = actions
+          return (create_actions_parser(statechart.scope), when_done)
+
+        def parse_transition(el):
+          nonlocal next_after_id
+          
+          if parent is root:
+            raise XmlError("Root <state> cannot be source of a transition.")
+
+          target_string = require_attribute(el, "target")
+          scope = Scope("transition", parent=statechart.scope)
+          transition = Transition(parent, [], scope, target_string)
+
+          event = el.get("event")
+          if event is not None:
+            positive_events, negative_events = parse_events_decl(globals, event)
+
+            def process_event_decl(e: EventDecl):
+              for i,p in enumerate(e.params):
+                scope.add_event_parameter(event_name=e.name, param_name=p.name, type=p.type, param_offset=i)
+
+            for e in itertools.chain(positive_events, negative_events):
+              process_event_decl(e)
+
+            if not negative_events:
+              transition.trigger = Trigger(positive_events)
+            else:
+              transition.trigger = NegatedTrigger(positive_events, negative_events)
+
+          after = el.get("after")
+          if after is not None:
+            if event is not None:
+              raise XmlError("Cannot specify 'after' and 'event' at the same time.")
+            try:
+              after_expr = parse_expression(globals, after)
+              after_type = after_expr.init_rvalue(scope)
+              if after_type != Duration:
+                msg = "Expression is '%s' type. Expected 'Duration' type." % str(after_type)
+                if after_type == int:
+                  msg += "\n Hint: Did you forget a duration unit sufix? ('s', 'ms', ...)"
+                raise Exception(msg)
+              event = "_after%d" % next_after_id # transition gets unique event name
+              transition.trigger = AfterTrigger(globals.events.assign_id(event), event, next_after_id, after_expr)
+              next_after_id += 1
+            except Exception as e:
+              raise XmlError("after=\"%s\": %s" % (after, str(e))) from e
+
+          cond = el.get("cond")
+          if cond is not None:
+            try:
+              expr = parse_expression(globals, cond)
+              expr.init_rvalue(scope)
+            except Exception as e:
+              raise XmlError("cond=\"%s\": %s" % (cond, str(e))) from e
+            transition.guard = expr
+
+          def when_done(*actions):
+            transition.actions = actions
+            transitions.append(transition)
+            parent.transitions.append(transition)
+
+          return (create_actions_parser(scope), when_done)
+
+        return {"state": parse_state, "parallel": parse_parallel, "history": parse_history, "onentry": parse_onentry, "onexit": parse_onexit, "transition": parse_transition}
+
+      def when_done():
+        deal_with_initial(el, root, children_dict)
+
+        for transition in transitions:
+          try:
+            parse_tree = parse_state_ref(transition.target_string)
+          except Exception as e:
+            raise XmlErrorElement(t_el, "Parsing target '%s': %s" % (target_string, str(e))) from e
+
+          def find_state(sequence) -> State:
+            if sequence.data == "relative_path":
+              state = transition.source
+            elif sequence.data == "absolute_path":
+              state = root
+            for item in sequence.children:
+              if item.type == "PARENT_NODE":
+                state = state.parent
+              elif item.type == "CURRENT_NODE":
+                continue
+              elif item.type == "IDENTIFIER":
+                state = [x for x in state.children if x.short_name == item.value][0]
+            return state
+
+          try:
+            transition.targets = [find_state(seq) for seq in parse_tree.children]
+          except Exception as e:
+            raise XmlErrorElement(t_el, "Could not find target '%s'." % (target_string)) from e
+
+        statechart.tree = StateTree(root)
+
+      return (create_state_parser(root, sibling_dict=children_dict), when_done)
+
+    def when_done():
+      return statechart
+
+    return ([("semantics?", parse_semantics), ("override_semantics?", parse_semantics), ("datamodel?", parse_datamodel), ("inport*", parse_inport), ("outport*", parse_outport), ("root", parse_root)], when_done)
+
+  return ([("statechart", parse_statechart)])

+ 4 - 6
src/sccd/syntax/statechart.py

@@ -76,14 +76,12 @@ class VariableSemantics:
 
     return [Semantics(**{f.name: o for f,o in zip(my_fields, variant)}) for variant in variants]
 
-@dataclass
-class StatechartVariableSemantics:
-  tree: StateTree
-  semantics: VariableSemantics
-  scope: Scope
 
 @dataclass
 class Statechart:
+  inport_events: Dict[str, Set[int]] # mapping from inport to set of event IDs
+  event_outport: Dict[str, str] # mapping from event name to outport
+
+  semantics: Union[VariableSemantics, Semantics]
   tree: StateTree
-  semantics: Semantics
   scope: Scope

+ 1 - 1
src/sccd/syntax/statement.py

@@ -95,7 +95,7 @@ class Block(Statement):
     def render(self) -> str:
         result = ""
         for stmt in self.stmts:
-            result += stmt.render() + ' '
+            result += stmt.render() + ' '
         return result
 
 # e.g. a function call

+ 23 - 5
src/sccd/syntax/tree.py

@@ -85,6 +85,7 @@ class ParallelState(State):
 
 @dataclass
 class EventDecl:
+    id: int
     name: str
     params: List[Param]
 
@@ -96,17 +97,31 @@ class EventDecl:
 
 @dataclass
 class Trigger:
-    enabling: Bitmap
+    enabling: List[EventDecl]
+
+    def __post_init__(self):
+        self.enabling_bitmap = Bitmap.from_list(e.id for e in self.enabling)
 
     def check(self, events_bitmap: Bitmap) -> bool:
-        return (self.enabling & events_bitmap) == self.enabling
+        return (self.enabling_bitmap & events_bitmap) == self.enabling_bitmap
+
+    def render(self) -> str:
+        return ' ∧ '.join(e.name for e in self.enabling)
 
 @dataclass
-class NegatedTrigger(Trigger):
-    disabling: Bitmap
+class NegatedTrigger:
+    enabling: List[EventDecl]
+    disabling: List[EventDecl]
+
+    def __post_init__(self):
+        self.enabling_bitmap = Bitmap.from_list(e.id for e in self.enabling)
+        self.disabling_bitmap = Bitmap.from_list(e.id for e in self.disabling)
 
     def check(self, events_bitmap: Bitmap) -> bool:
-        return Trigger.check(self, events_bitmap) and not (self.disabling & events_bitmap)
+        return (self.enabling_bitmap & events_bitmap) == self.enabling_bitmap and not (self.disabling_bitmap & events_bitmap)
+
+    def render(self) -> str:
+        return ' ∧ '.join(e.name for e in self.enabling) + ' ∧ ' + ' ∧ '.join('¬'+e.name for e in self.disabling)
 
 @dataclass
 class EventTrigger:
@@ -146,6 +161,9 @@ class AfterTrigger(EventTrigger):
 class Transition:
     source: State
     targets: List[State]
+    scope: Scope
+
+    target_string: Optional[str] = None
 
     guard: Optional[Expression] = None
     actions: List[Action] = field(default_factory=list)

+ 3 - 5
test/lib/test.py

@@ -16,14 +16,12 @@ class Test(unittest.TestCase):
     return self.src
 
   def runTest(self):
-    parser = TestParser()
-    parser.tests.push([])
+    parser = create_test_parser(self.src)
     try:
-      statechart = parser.parse(self.src)
+      test_variants = parse(self.src, parser)
     except Exception as e:
       print_debug(e)
-      raise
-    test_variants = parser.tests.pop()
+      raise e
 
     for test in test_variants:
       print_debug('\n'+test.name)

+ 72 - 102
test/lib/test_parser.py

@@ -1,8 +1,8 @@
-import os
 from sccd.parser.statechart_parser import *
-from sccd.parser.expression_parser import *
-from lib.test import *
-from copy import deepcopy
+from sccd.model.globals import *
+from sccd.controller.controller import InputEvent
+from sccd.execution.event import Event
+from sccd.model.model import *
 
 @dataclass
 class TestVariant:
@@ -11,107 +11,77 @@ class TestVariant:
   input: list
   output: list
 
-# Parses <test> element and all its children (including <statechart>)
-class TestParser(StatechartParser):
-
-  def __init__(self):
-    super().__init__()
-    self.tests = XmlParser.Context("tests")
-    self.globals = XmlParser.Context("globals")
-    self.test_input = XmlParser.Context("test_input")
-    self.test_output = XmlParser.Context("test_output")
-    self.big_step = XmlParser.Context("big_step")
-
-  def end_event(self, el):
-    big_step = self.big_step.require()
-    name = el.get("name")
-    port = el.get("port")
-
-    if name is None:
-      raise Exception("missing attribute 'name'")
-    if port is None:
-      raise Exception("missing attribute 'port'")
-      
-    big_step.append(Event(id=0, name=name, port=port, parameters=[]))
-
-  def start_big_step(self, el):
-    self.test_output.require()
-    self.big_step.push([])
-
-  def end_big_step(self, el):
-    output = self.test_output.require()
-    big_step = self.big_step.pop()
-    output.append(big_step)
-
-  def end_input_event(self, el):
-    input = self.test_input.require()
-    globals = self.globals.require()
-    name = el.get("name")
-    port = el.get("port")
-    time = el.get("time")
-
-    if name is None:
-      raise Exception("missing attribute 'name'")
-    if port is None:
-      raise Exception("missing attribute 'port'")
-    if time is None:
-      raise Exception("missing attribute 'time'")
-
-    duration = parse_duration(globals, time)
-    input.append(InputEvent(name=name, port=port, parameters=[], time_offset=duration))
-
-  def start_input(self, el):
-    self.test_input.require()
-
-  def end_input(self, el):
-    pass
-
-  def start_output(self, el):
-    self.test_output.require()
-
-  def end_output(self, el):
-    pass
-
-  def start_test(self, el):
-    self.globals.push(Globals(fixed_delta = None))
-    self.test_input.push([])
-    self.test_output.push([])
-    self.statecharts.push([])
-
-  def end_test(self, el):
-    tests = self.tests.require()
-    src_file = self.src_file.require()
-
-    statecharts = self.statecharts.pop()
-    input = self.test_input.pop()
-    output = self.test_output.pop()
-    globals = self.globals.pop()
-
-    if len(statecharts) != 1:
-      raise Exception("Expected exactly 1 <statechart> node, got %d." % len(statecharts))
-    statechart = statecharts[0]
-
-    globals.process_durations()
-
-    variants = statechart.semantics.generate_variants()
-
-    def variant_description(i, variant) -> str:
-      if not variant:
-        return ""
-      text = "Semantic variant %d of %d:" % (i+1, len(variants))
-      for f in fields(variant):
-        text += "\n  %s: %s" % (f.name, getattr(variant, f.name))
-      return text
-
-    # Generate test variants for all semantic wildcards filled in
-    tests.extend(
-      TestVariant(
+def create_test_parser(src_file, load_external = True):
+  globals = Globals(fixed_delta=None)
+  parse_statechart = create_statechart_parser(globals, src_file, load_external)
+  input = []
+  output = []
+
+  def parse_test(el):
+    def parse_input(el):
+      def parse_input_event(el):
+        name = el.get("name")
+        port = el.get("port")
+        time = el.get("time")
+
+        if name is None:
+          raise XmlError("missing attribute 'name'")
+        if port is None:
+          raise XmlError("missing attribute 'port'")
+        if time is None:
+          raise XmlError("missing attribute 'time'")
+
+        duration = parse_duration(globals, time)
+        input.append(InputEvent(name=name, port=port, parameters=[], time_offset=duration))
+
+      return [("event+", parse_input_event)]
+
+    def parse_output(el):
+      def parse_big_step(el):
+        big_step = []
+        output.append(big_step)
+
+        def parse_output_event(el):
+          name = el.get("name")
+          port = el.get("port")
+
+          if name is None:
+            raise XmlError("missing attribute 'name'")
+          if port is None:
+            raise XmlError("missing attribute 'port'")
+
+          big_step.append(Event(id=0, name=name, port=port, parameters=[]))
+
+        return [("event+", parse_output_event)]
+
+      return [("big_step+", parse_big_step)]
+
+    def when_done(statechart):
+      globals.process_durations()
+      variants = statechart.semantics.generate_variants()
+
+      def variant_description(i, variant) -> str:
+        if not variant:
+          return ""
+        text = "Semantic variant %d of %d:" % (i+1, len(variants))
+        for f in fields(variant):
+          text += "\n  %s: %s" % (f.name, getattr(variant, f.name))
+        return text
+
+      return [TestVariant(
         name=variant_description(i, variant),
         model=SingleInstanceModel(
           globals,
-          Statechart(tree=statechart.tree, scope=statechart.scope, semantics=variant)),
+          Statechart(
+            inport_events={},
+            event_outport={},
+            tree=statechart.tree,
+            scope=statechart.scope,
+            semantics=variant)),
         input=input,
         output=output)
+      for i, variant in enumerate(variants)]
+
+    return (parse_statechart + [("input?", parse_input), ("output?", parse_output)], when_done)
 
-      for i, variant in enumerate(variants)
-    )
+  return [("test", parse_test)]

+ 10 - 10
test/render.py

@@ -36,15 +36,13 @@ if __name__ == '__main__':
 
     def process(src):
       try:
-        parser = StatechartParser(load_external = False)
-        parser.globals.push(Globals(fixed_delta = None))
-        parser.statecharts.push([])
-        parser.parse(src)
-        statecharts = parser.statecharts.pop()
-        if len(statecharts) != 1:
+        parser = create_statechart_parser(Globals(), src, load_external=False)
+        statechart = parse(src, parser,
+          ignore_unmatched=True, disable_multiplicities=True)
+
+        if statechart is None:
           return # no statechart here :(
 
-        statechart = statecharts[0]
         root = statechart.tree.root
 
         target_path = lambda ext: os.path.join(args.output_dir, dropext(src)+ext)
@@ -156,10 +154,12 @@ if __name__ == '__main__':
           print("Wrote "+svg_target)
         if not args.keep_smcat:
           os.remove(smcat_target)
-          
+      
+      except SkipFile:
+        pass
       except Exception as e:
-        # import traceback
-        # traceback.print_exception(type(e), e, None)
+        import traceback
+        traceback.print_exception(type(e), e, None)
         print(e,'\n')
 
     pool_size = min(args.pool_size, len(srcs))

+ 4 - 4
test/test_files/day_atlee/fail_02_counter_takemany.xml

@@ -6,10 +6,10 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
   </input>
 
   <output>

+ 39 - 39
test/test_files/day_atlee/statechart_fig1_redialer.svg

@@ -4,25 +4,25 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="812pt" height="394pt"
- viewBox="0.00 0.00 812.00 394.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="805pt" height="394pt"
+ viewBox="0.00 0.00 805.00 394.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 390)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-390 808,-390 808,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-390 801,-390 801,4 -4,4"/>
 <g id="clust1" class="cluster">
 <title>cluster__Dialing</title>
-<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 784,-8 784,-8 790,-8 796,-14 796,-20 796,-20 796,-335 796,-335 796,-341 790,-347 784,-347 784,-347 20,-347 20,-347 14,-347 8,-341 8,-335 8,-335 8,-20 8,-20 8,-14 14,-8 20,-8"/>
-<text text-anchor="start" x="383.6682" y="-328.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Dialing</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 777,-8 777,-8 783,-8 789,-14 789,-20 789,-20 789,-335 789,-335 789,-341 783,-347 777,-347 777,-347 20,-347 20,-347 14,-347 8,-341 8,-335 8,-335 8,-20 8,-20 8,-14 14,-8 20,-8"/>
+<text text-anchor="start" x="380.1682" y="-328.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Dialing</text>
 </g>
 <g id="clust2" class="cluster">
 <title>cluster__Dialing_Redialer</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="445,-16 445,-309 788,-309 788,-16 445,-16"/>
-<text text-anchor="start" x="594.1668" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Redialer</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="438,-16 438,-309 781,-309 781,-16 438,-16"/>
+<text text-anchor="start" x="587.1668" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Redialer</text>
 </g>
 <g id="clust3" class="cluster">
 <title>cluster__Dialing_Dialer</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-16 24,-309 437,-309 437,-16 24,-16"/>
-<text text-anchor="start" x="215.3376" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Dialer</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-16 24,-309 430,-309 430,-16 24,-16"/>
+<text text-anchor="start" x="211.8376" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Dialer</text>
 </g>
 <!-- __initial -->
 <g id="node1" class="node">
@@ -41,49 +41,49 @@
 <!-- _Dialing_Redialer_initial -->
 <g id="node4" class="node">
 <title>_Dialing_Redialer_initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="559" cy="-265.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="552" cy="-265.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _Dialing_Redialer_WaitForRedial -->
 <g id="node6" class="node">
 <title>_Dialing_Redialer_WaitForRedial</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="614.5,-178 503.5,-178 503.5,-142 614.5,-142 614.5,-178"/>
-<text text-anchor="start" x="514.8342" y="-156.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">WaitForRedial ✓</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M515.8333,-143C515.8333,-143 602.1667,-143 602.1667,-143 607.8333,-143 613.5,-148.6667 613.5,-154.3333 613.5,-154.3333 613.5,-165.6667 613.5,-165.6667 613.5,-171.3333 607.8333,-177 602.1667,-177 602.1667,-177 515.8333,-177 515.8333,-177 510.1667,-177 504.5,-171.3333 504.5,-165.6667 504.5,-165.6667 504.5,-154.3333 504.5,-154.3333 504.5,-148.6667 510.1667,-143 515.8333,-143"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="607.5,-178 496.5,-178 496.5,-142 607.5,-142 607.5,-178"/>
+<text text-anchor="start" x="507.8342" y="-156.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">WaitForRedial ✓</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M508.8333,-143C508.8333,-143 595.1667,-143 595.1667,-143 600.8333,-143 606.5,-148.6667 606.5,-154.3333 606.5,-154.3333 606.5,-165.6667 606.5,-165.6667 606.5,-171.3333 600.8333,-177 595.1667,-177 595.1667,-177 508.8333,-177 508.8333,-177 503.1667,-177 497.5,-171.3333 497.5,-165.6667 497.5,-165.6667 497.5,-154.3333 497.5,-154.3333 497.5,-148.6667 503.1667,-143 508.8333,-143"/>
 </g>
 <!-- _Dialing_Redialer_initial&#45;&gt;_Dialing_Redialer_WaitForRedial -->
 <g id="edge2" class="edge">
 <title>_Dialing_Redialer_initial&#45;&gt;_Dialing_Redialer_WaitForRedial</title>
-<path fill="none" stroke="#000000" d="M559,-259.8288C559,-255.1736 559,-248.4097 559,-242.5 559,-242.5 559,-242.5 559,-195.5 559,-193.1079 559,-190.6252 559,-188.1342"/>
-<polygon fill="#000000" stroke="#000000" points="562.5001,-188.0597 559,-178.0598 555.5001,-188.0598 562.5001,-188.0597"/>
-<text text-anchor="middle" x="560.3895" y="-216" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M552,-259.8288C552,-255.1736 552,-248.4097 552,-242.5 552,-242.5 552,-242.5 552,-195.5 552,-193.1079 552,-190.6252 552,-188.1342"/>
+<polygon fill="#000000" stroke="#000000" points="555.5001,-188.0597 552,-178.0598 548.5001,-188.0598 555.5001,-188.0597"/>
+<text text-anchor="middle" x="553.3895" y="-216" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _Dialing_Redialer_RedialDigits -->
 <g id="node5" class="node">
 <title>_Dialing_Redialer_RedialDigits</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="568.5,-60 483.5,-60 483.5,-24 568.5,-24 568.5,-60"/>
-<text text-anchor="start" x="494.5026" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">RedialDigits</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M495.8333,-25C495.8333,-25 556.1667,-25 556.1667,-25 561.8333,-25 567.5,-30.6667 567.5,-36.3333 567.5,-36.3333 567.5,-47.6667 567.5,-47.6667 567.5,-53.3333 561.8333,-59 556.1667,-59 556.1667,-59 495.8333,-59 495.8333,-59 490.1667,-59 484.5,-53.3333 484.5,-47.6667 484.5,-47.6667 484.5,-36.3333 484.5,-36.3333 484.5,-30.6667 490.1667,-25 495.8333,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="561.5,-60 476.5,-60 476.5,-24 561.5,-24 561.5,-60"/>
+<text text-anchor="start" x="487.5026" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">RedialDigits</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M488.8333,-25C488.8333,-25 549.1667,-25 549.1667,-25 554.8333,-25 560.5,-30.6667 560.5,-36.3333 560.5,-36.3333 560.5,-47.6667 560.5,-47.6667 560.5,-53.3333 554.8333,-59 549.1667,-59 549.1667,-59 488.8333,-59 488.8333,-59 483.1667,-59 477.5,-53.3333 477.5,-47.6667 477.5,-47.6667 477.5,-36.3333 477.5,-36.3333 477.5,-30.6667 483.1667,-25 488.8333,-25"/>
 </g>
 <!-- _Dialing_Redialer_RedialDigits&#45;&gt;_Dialing_Redialer_RedialDigits -->
 <g id="edge3" class="edge">
 <title>_Dialing_Redialer_RedialDigits&#45;&gt;_Dialing_Redialer_RedialDigits</title>
-<path fill="none" stroke="#000000" d="M568.7986,-46.856C581.0518,-46.6655 590.5,-45.0469 590.5,-42 590.5,-39.8577 585.8289,-38.4214 578.7961,-37.6913"/>
-<polygon fill="#000000" stroke="#000000" points="578.9749,-34.1959 568.7986,-37.144 578.5923,-41.1855 578.9749,-34.1959"/>
-<text text-anchor="start" x="590.5" y="-39" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[c &lt; numdigits(p)]^dial(digit(p, c+1)) &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M561.7986,-46.856C574.0518,-46.6655 583.5,-45.0469 583.5,-42 583.5,-39.8577 578.8289,-38.4214 571.7961,-37.6913"/>
+<polygon fill="#000000" stroke="#000000" points="571.9749,-34.1959 561.7986,-37.144 571.5923,-41.1855 571.9749,-34.1959"/>
+<text text-anchor="start" x="583.5" y="-39" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[c &lt; numdigits(p)]^dial(digit(p, c+1)) &#160;&#160;</text>
 </g>
 <!-- _Dialing_Redialer_RedialDigits&#45;&gt;_Dialing_Redialer_WaitForRedial -->
 <g id="edge4" class="edge">
 <title>_Dialing_Redialer_RedialDigits&#45;&gt;_Dialing_Redialer_WaitForRedial</title>
-<path fill="none" stroke="#000000" d="M483.4216,-59.8718C478.3898,-64.5715 475,-70.3799 475,-77.5 475,-124.5 475,-124.5 475,-124.5 475,-130.7463 482.9804,-136.5147 494.0215,-141.5063"/>
-<polygon fill="#000000" stroke="#000000" points="492.8568,-144.811 503.4386,-145.3373 495.4946,-138.327 492.8568,-144.811"/>
-<text text-anchor="start" x="475" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[c == numdigits(p)] &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M476.4216,-59.8718C471.3898,-64.5715 468,-70.3799 468,-77.5 468,-124.5 468,-124.5 468,-124.5 468,-130.7463 475.9804,-136.5147 487.0215,-141.5063"/>
+<polygon fill="#000000" stroke="#000000" points="485.8568,-144.811 496.4386,-145.3373 488.4946,-138.327 485.8568,-144.811"/>
+<text text-anchor="start" x="468" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[c == numdigits(p)] &#160;&#160;</text>
 </g>
 <!-- _Dialing_Redialer_WaitForRedial&#45;&gt;_Dialing_Redialer_RedialDigits -->
 <g id="edge5" class="edge">
 <title>_Dialing_Redialer_WaitForRedial&#45;&gt;_Dialing_Redialer_RedialDigits</title>
-<path fill="none" stroke="#000000" d="M602.0313,-141.6979C606.8125,-137.0752 610,-131.4043 610,-124.5 610,-124.5 610,-124.5 610,-77.5 610,-69.0842 595.5133,-61.5359 578.5722,-55.5861"/>
-<polygon fill="#000000" stroke="#000000" points="579.5769,-52.2323 568.9843,-52.4497 577.4005,-58.8854 579.5769,-52.2323"/>
-<text text-anchor="start" x="610" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">redial [c == 0]/p = lp ^dial(digit(lp, 1)) &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M595.0313,-141.6979C599.8125,-137.0752 603,-131.4043 603,-124.5 603,-124.5 603,-124.5 603,-77.5 603,-69.0842 588.5133,-61.5359 571.5722,-55.5861"/>
+<polygon fill="#000000" stroke="#000000" points="572.5769,-52.2323 561.9843,-52.4497 570.4005,-58.8854 572.5769,-52.2323"/>
+<text text-anchor="start" x="603" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">redial [c == 0]/p = lp ^dial(digit(lp, 1)) &#160;&#160;</text>
 </g>
 <!-- _Dialing_Dialer -->
 <!-- _Dialing_Dialer_initial -->
@@ -108,37 +108,37 @@
 <!-- _Dialing_Dialer_DialDigits -->
 <g id="node9" class="node">
 <title>_Dialing_Dialer_DialDigits</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="140,-60 68,-60 68,-24 140,-24 140,-60"/>
-<text text-anchor="start" x="78.6734" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">DialDigits</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M80.3333,-25C80.3333,-25 127.6667,-25 127.6667,-25 133.3333,-25 139,-30.6667 139,-36.3333 139,-36.3333 139,-47.6667 139,-47.6667 139,-53.3333 133.3333,-59 127.6667,-59 127.6667,-59 80.3333,-59 80.3333,-59 74.6667,-59 69,-53.3333 69,-47.6667 69,-47.6667 69,-36.3333 69,-36.3333 69,-30.6667 74.6667,-25 80.3333,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="141,-60 69,-60 69,-24 141,-24 141,-60"/>
+<text text-anchor="start" x="79.6734" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">DialDigits</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M81.3333,-25C81.3333,-25 128.6667,-25 128.6667,-25 134.3333,-25 140,-30.6667 140,-36.3333 140,-36.3333 140,-47.6667 140,-47.6667 140,-53.3333 134.3333,-59 128.6667,-59 128.6667,-59 81.3333,-59 81.3333,-59 75.6667,-59 70,-53.3333 70,-47.6667 70,-47.6667 70,-36.3333 70,-36.3333 70,-30.6667 75.6667,-25 81.3333,-25"/>
 </g>
 <!-- _Dialing_Dialer_DialDigits&#45;&gt;_Dialing_Dialer_DialDigits -->
 <g id="edge7" class="edge">
 <title>_Dialing_Dialer_DialDigits&#45;&gt;_Dialing_Dialer_DialDigits</title>
-<path fill="none" stroke="#000000" d="M140.25,-46.875C152.3333,-46.875 162,-45.25 162,-42 162,-39.7656 157.431,-38.2993 150.6489,-37.6011"/>
-<polygon fill="#000000" stroke="#000000" points="150.3996,-34.0861 140.25,-37.125 150.0794,-41.0788 150.3996,-34.0861"/>
-<text text-anchor="start" x="162" y="-39" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial(d:int) [c &lt; 10]/lp = lp * 10 + d c += 1 &#160;^out.out(d) &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M141.25,-46.875C153.3333,-46.875 163,-45.25 163,-42 163,-39.7656 158.431,-38.2993 151.6489,-37.6011"/>
+<polygon fill="#000000" stroke="#000000" points="151.3996,-34.0861 141.25,-37.125 151.0794,-41.0788 151.3996,-34.0861"/>
+<text text-anchor="start" x="163" y="-39" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial [c &lt; 10]/lp = lp * 10 + d c += 1 &#160;^out.out(d) &#160;&#160;</text>
 </g>
 <!-- _Dialing_Dialer_DialDigits&#45;&gt;_Dialing_Dialer_WaitForDial -->
 <g id="edge8" class="edge">
 <title>_Dialing_Dialer_DialDigits&#45;&gt;_Dialing_Dialer_WaitForDial</title>
-<path fill="none" stroke="#000000" d="M74.4875,-60.3273C70.0916,-65.167 67,-70.9124 67,-77.5 67,-124.5 67,-124.5 67,-124.5 67,-126.9367 67.2734,-129.4132 67.7409,-131.8668"/>
+<path fill="none" stroke="#000000" d="M74.6899,-60.1859C70.1752,-65.0344 67,-70.8191 67,-77.5 67,-124.5 67,-124.5 67,-124.5 67,-126.9367 67.2734,-129.4132 67.7409,-131.8668"/>
 <polygon fill="#000000" stroke="#000000" points="64.4295,-133.0164 70.5523,-141.6629 71.1579,-131.0853 64.4295,-133.0164"/>
 <text text-anchor="start" x="67" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[c == 10] &#160;&#160;</text>
 </g>
 <!-- _Dialing_Dialer_WaitForDial&#45;&gt;_Dialing_Dialer_DialDigits -->
 <g id="edge10" class="edge">
 <title>_Dialing_Dialer_WaitForDial&#45;&gt;_Dialing_Dialer_DialDigits</title>
-<path fill="none" stroke="#000000" d="M128.5115,-146.0105C144.3736,-139.9675 158,-132.4599 158,-124.5 158,-124.5 158,-124.5 158,-77.5 158,-69.8638 154.1829,-63.7787 148.5785,-58.9596"/>
-<polygon fill="#000000" stroke="#000000" points="150.2577,-55.8692 140.0188,-53.1463 146.3249,-61.66 150.2577,-55.8692"/>
-<text text-anchor="start" x="158" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial(d:int), redial [c == 0]/lp = d c = 1 &#160;^out.out(d) &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M128.5115,-146.0105C144.3736,-139.9675 158,-132.4599 158,-124.5 158,-124.5 158,-124.5 158,-77.5 158,-70.3568 154.6355,-64.5595 149.602,-59.8834"/>
+<polygon fill="#000000" stroke="#000000" points="151.3797,-56.849 141.2305,-53.8085 147.2684,-62.5145 151.3797,-56.849"/>
+<text text-anchor="start" x="158" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial ∧ redial [c == 0]/lp = d⁏ c = 1⁏ &#160;^out.out(d) &#160;&#160;</text>
 </g>
 <!-- _Dialing_Dialer_WaitForDial&#45;&gt;_Dialing_Dialer_WaitForDial -->
 <g id="edge9" class="edge">
 <title>_Dialing_Dialer_WaitForDial&#45;&gt;_Dialing_Dialer_WaitForDial</title>
 <path fill="none" stroke="#000000" d="M128.7649,-164.8167C141.1797,-164.5001 150.5,-162.8945 150.5,-160 150.5,-157.9648 145.8922,-156.5668 138.8407,-155.8061"/>
 <polygon fill="#000000" stroke="#000000" points="138.9618,-152.307 128.7649,-155.1833 138.5299,-159.2937 138.9618,-152.307"/>
-<text text-anchor="start" x="150.5" y="-157" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial(d:int), not redial [c &lt; 10]/c += 1 lp = lp * 10 + d &#160;^out.out(d) &#160;&#160;</text>
+<text text-anchor="start" x="150.5" y="-157" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial ∧ ¬redial [c &lt; 10]/c += 1⁏ lp = lp * 10 + d⁏ &#160;^out.out(d) &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 53 - 55
test/test_files/day_atlee/statechart_fig1_redialer.xml

@@ -19,63 +19,61 @@
     </func>
   </datamodel>
 
-  <tree>
-    <state>
-      <parallel id="Dialing">
-        <state id="Dialer" initial="WaitForDial">
-          <state id="WaitForDial" stable="true">
-            <!-- t1 -->
-            <transition event="dial(d:int), not redial" cond="c &lt; 10" target=".">
-              <code>
-                c += 1;
-                lp = lp * 10 + d;
-              </code>
-              <raise port="out" event="out(d)"/>
-            </transition>
-            <!-- t2 -->
-            <transition event="dial(d:int), redial" cond="c == 0" target="../DialDigits">
-              <code>
-                lp = d;
-                c = 1;
-              </code>
-              <raise port="out" event="out(d)"/>
-            </transition>
-          </state>
-          <state id="DialDigits">
-            <!-- t3 -->
-            <transition event="dial(d:int)" cond="c &lt; 10" target=".">
-              <code>
-                lp = lp * 10 + d;
-                c += 1;
-              </code>
-              <raise port="out" event="out(d)"/>
-            </transition>
-            <!-- t4 -->
-            <transition cond="c == 10" target="../WaitForDial"/>
-          </state>
+  <root>
+    <parallel id="Dialing">
+      <state id="Dialer" initial="WaitForDial">
+        <state id="WaitForDial" stable="true">
+          <!-- t1 -->
+          <transition event="dial(d:int), not redial" cond="c &lt; 10" target=".">
+            <code>
+              c += 1;
+              lp = lp * 10 + d;
+            </code>
+            <raise port="out" event="out(d)"/>
+          </transition>
+          <!-- t2 -->
+          <transition event="dial(d:int), redial" cond="c == 0" target="../DialDigits">
+            <code>
+              lp = d;
+              c = 1;
+            </code>
+            <raise port="out" event="out(d)"/>
+          </transition>
         </state>
+        <state id="DialDigits">
+          <!-- t3 -->
+          <transition event="dial(d:int)" cond="c &lt; 10" target=".">
+            <code>
+              lp = lp * 10 + d;
+              c += 1;
+            </code>
+            <raise port="out" event="out(d)"/>
+          </transition>
+          <!-- t4 -->
+          <transition cond="c == 10" target="../WaitForDial"/>
+        </state>
+      </state>
 
-        <state id="Redialer" initial="WaitForRedial">
-          <state id="WaitForRedial" stable="true">
-            <!-- t5 -->
-            <transition event="redial" cond="c == 0" target="../RedialDigits">
-              <code>
-                p = lp;
-              </code>
-              <raise event="dial(digit(lp, 1))"/>
-            </transition>
-          </state>
-          <state id="RedialDigits">
-            <!-- t6 -->
-            <transition cond="c &lt; numdigits(p)" target=".">
-              <raise event="dial(digit(p, c+1))"/>
-            </transition>
-            <!-- t7 -->
-            <transition cond="c == numdigits(p)" target="../WaitForRedial"/>
-          </state>
+      <state id="Redialer" initial="WaitForRedial">
+        <state id="WaitForRedial" stable="true">
+          <!-- t5 -->
+          <transition event="redial" cond="c == 0" target="../RedialDigits">
+            <code>
+              p = lp;
+            </code>
+            <raise event="dial(digit(lp, 1))"/>
+          </transition>
+        </state>
+        <state id="RedialDigits">
+          <!-- t6 -->
+          <transition cond="c &lt; numdigits(p)" target=".">
+            <raise event="dial(digit(p, c+1))"/>
+          </transition>
+          <!-- t7 -->
+          <transition cond="c == numdigits(p)" target="../WaitForRedial"/>
         </state>
+      </state>
 
-      </parallel>
-    </state>
-  </tree>
+    </parallel>
+  </root>
 </statechart>

+ 4 - 4
test/test_files/day_atlee/statechart_fig7_dialer.svg

@@ -4,11 +4,11 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="225pt" height="83pt"
- viewBox="0.00 0.00 224.92 83.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="214pt" height="83pt"
+ viewBox="0.00 0.00 214.36 83.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 79)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-79 220.917,-79 220.917,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-79 210.36,-79 210.36,4 -4,4"/>
 <!-- __initial -->
 <g id="node1" class="node">
 <title>__initial</title>
@@ -33,7 +33,7 @@
 <title>_D&#45;&gt;_D</title>
 <path fill="none" stroke="#000000" d="M56.0183,-23.9381C67.888,-24.3856 78,-22.4063 78,-18 78,-14.9707 73.2205,-13.0885 66.3762,-12.3533"/>
 <polygon fill="#000000" stroke="#000000" points="66.1128,-8.8446 56.0183,-12.0619 65.9158,-15.8419 66.1128,-8.8446"/>
-<text text-anchor="start" x="78" y="-15" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.dial [c &lt; 10]/c += 1 ^out.out &#160;&#160;</text>
+<text text-anchor="start" x="78" y="-15" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dial [c &lt; 10]/c += 1 ^out.out &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 9 - 12
test/test_files/day_atlee/statechart_fig7_dialer.xml

@@ -6,17 +6,14 @@
     <var id="c" expr="0"/>
   </datamodel>
 
-  <tree>
-    <state initial="D">
-      <state id="D">
-        <transition port="in" event="dial" cond="c &lt; 10" target=".">
-          <parameter name="d" />
-          <code> c += 1; </code>
-          <raise port="out" event="out">
-            <parameter expr="d"/>
-          </raise>
-        </transition>
-      </state>
+  <root initial="D">
+    <state id="D">
+      <transition port="in" event="dial(d:int)" cond="c &lt; 10" target=".">
+        <code> c += 1; </code>
+        <raise port="out" event="out">
+          <!-- <parameter expr="d"/> -->
+        </raise>
+      </transition>
     </state>
-  </tree>
+  </root>
 </statechart>

+ 41 - 41
test/test_files/day_atlee/statechart_fig8_counter.svg

@@ -4,25 +4,25 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="389pt" height="394pt"
- viewBox="0.00 0.00 389.00 394.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="369pt" height="394pt"
+ viewBox="0.00 0.00 369.00 394.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 390)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-390 385,-390 385,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-390 365,-390 365,4 -4,4"/>
 <g id="clust1" class="cluster">
 <title>cluster__Counter</title>
-<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 361,-8 361,-8 367,-8 373,-14 373,-20 373,-20 373,-335 373,-335 373,-341 367,-347 361,-347 361,-347 20,-347 20,-347 14,-347 8,-341 8,-335 8,-335 8,-20 8,-20 8,-14 14,-8 20,-8"/>
-<text text-anchor="start" x="169.1622" y="-328.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Counter</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 341,-8 341,-8 347,-8 353,-14 353,-20 353,-20 353,-335 353,-335 353,-341 347,-347 341,-347 341,-347 20,-347 20,-347 14,-347 8,-341 8,-335 8,-335 8,-20 8,-20 8,-14 14,-8 20,-8"/>
+<text text-anchor="start" x="159.1622" y="-328.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Counter</text>
 </g>
 <g id="clust2" class="cluster">
 <title>cluster__Counter_Bit_2</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="196,-16 196,-309 365,-309 365,-16 196,-16"/>
-<text text-anchor="start" x="267.329" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_2</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="176,-16 176,-309 345,-309 345,-16 176,-16"/>
+<text text-anchor="start" x="247.329" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_2</text>
 </g>
 <g id="clust3" class="cluster">
 <title>cluster__Counter_Bit_1</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-16 24,-309 188,-309 188,-16 24,-16"/>
-<text text-anchor="start" x="92.829" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_1</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-16 24,-309 168,-309 168,-16 24,-16"/>
+<text text-anchor="start" x="82.829" y="-290.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_1</text>
 </g>
 <!-- __initial -->
 <g id="node1" class="node">
@@ -41,83 +41,83 @@
 <!-- _Counter_Bit_2_initial -->
 <g id="node4" class="node">
 <title>_Counter_Bit_2_initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="256" cy="-265.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="236" cy="-265.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _Counter_Bit_2_Bit_21 -->
 <g id="node6" class="node">
 <title>_Counter_Bit_2_Bit_21</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="284,-178 228,-178 228,-142 284,-142 284,-178"/>
-<text text-anchor="start" x="238.9936" y="-156.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_21</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M240.3333,-143C240.3333,-143 271.6667,-143 271.6667,-143 277.3333,-143 283,-148.6667 283,-154.3333 283,-154.3333 283,-165.6667 283,-165.6667 283,-171.3333 277.3333,-177 271.6667,-177 271.6667,-177 240.3333,-177 240.3333,-177 234.6667,-177 229,-171.3333 229,-165.6667 229,-165.6667 229,-154.3333 229,-154.3333 229,-148.6667 234.6667,-143 240.3333,-143"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="264,-178 208,-178 208,-142 264,-142 264,-178"/>
+<text text-anchor="start" x="218.9936" y="-156.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_21</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M220.3333,-143C220.3333,-143 251.6667,-143 251.6667,-143 257.3333,-143 263,-148.6667 263,-154.3333 263,-154.3333 263,-165.6667 263,-165.6667 263,-171.3333 257.3333,-177 251.6667,-177 251.6667,-177 220.3333,-177 220.3333,-177 214.6667,-177 209,-171.3333 209,-165.6667 209,-165.6667 209,-154.3333 209,-154.3333 209,-148.6667 214.6667,-143 220.3333,-143"/>
 </g>
 <!-- _Counter_Bit_2_initial&#45;&gt;_Counter_Bit_2_Bit_21 -->
 <g id="edge2" class="edge">
 <title>_Counter_Bit_2_initial&#45;&gt;_Counter_Bit_2_Bit_21</title>
-<path fill="none" stroke="#000000" d="M256,-259.8288C256,-255.1736 256,-248.4097 256,-242.5 256,-242.5 256,-242.5 256,-195.5 256,-193.1079 256,-190.6252 256,-188.1342"/>
-<polygon fill="#000000" stroke="#000000" points="259.5001,-188.0597 256,-178.0598 252.5001,-188.0598 259.5001,-188.0597"/>
-<text text-anchor="middle" x="257.3895" y="-216" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M236,-259.8288C236,-255.1736 236,-248.4097 236,-242.5 236,-242.5 236,-242.5 236,-195.5 236,-193.1079 236,-190.6252 236,-188.1342"/>
+<polygon fill="#000000" stroke="#000000" points="239.5001,-188.0597 236,-178.0598 232.5001,-188.0598 239.5001,-188.0597"/>
+<text text-anchor="middle" x="237.3895" y="-216" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _Counter_Bit_2_Bit_22 -->
 <g id="node5" class="node">
 <title>_Counter_Bit_2_Bit_22</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="309,-60 253,-60 253,-24 309,-24 309,-60"/>
-<text text-anchor="start" x="263.9936" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_22</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M265.3333,-25C265.3333,-25 296.6667,-25 296.6667,-25 302.3333,-25 308,-30.6667 308,-36.3333 308,-36.3333 308,-47.6667 308,-47.6667 308,-53.3333 302.3333,-59 296.6667,-59 296.6667,-59 265.3333,-59 265.3333,-59 259.6667,-59 254,-53.3333 254,-47.6667 254,-47.6667 254,-36.3333 254,-36.3333 254,-30.6667 259.6667,-25 265.3333,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="289,-60 233,-60 233,-24 289,-24 289,-60"/>
+<text text-anchor="start" x="243.9936" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_22</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M245.3333,-25C245.3333,-25 276.6667,-25 276.6667,-25 282.3333,-25 288,-30.6667 288,-36.3333 288,-36.3333 288,-47.6667 288,-47.6667 288,-53.3333 282.3333,-59 276.6667,-59 276.6667,-59 245.3333,-59 245.3333,-59 239.6667,-59 234,-53.3333 234,-47.6667 234,-47.6667 234,-36.3333 234,-36.3333 234,-30.6667 239.6667,-25 245.3333,-25"/>
 </g>
 <!-- _Counter_Bit_2_Bit_22&#45;&gt;_Counter_Bit_2_Bit_21 -->
 <g id="edge3" class="edge">
 <title>_Counter_Bit_2_Bit_22&#45;&gt;_Counter_Bit_2_Bit_21</title>
-<path fill="none" stroke="#000000" d="M252.8555,-49.0879C239.3237,-54.3567 226,-63.1802 226,-77.5 226,-124.5 226,-124.5 226,-124.5 226,-127.5259 226.6437,-130.4271 227.7426,-133.1752"/>
-<polygon fill="#000000" stroke="#000000" points="224.8185,-135.1048 232.958,-141.8871 230.8245,-131.5093 224.8185,-135.1048"/>
-<text text-anchor="start" x="226" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tk1^out.done &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M232.8555,-49.0879C219.3237,-54.3567 206,-63.1802 206,-77.5 206,-124.5 206,-124.5 206,-124.5 206,-127.5259 206.6437,-130.4271 207.7426,-133.1752"/>
+<polygon fill="#000000" stroke="#000000" points="204.8185,-135.1048 212.958,-141.8871 210.8245,-131.5093 204.8185,-135.1048"/>
+<text text-anchor="start" x="206" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tk1^out.done &#160;&#160;</text>
 </g>
 <!-- _Counter_Bit_2_Bit_21&#45;&gt;_Counter_Bit_2_Bit_22 -->
 <g id="edge4" class="edge">
 <title>_Counter_Bit_2_Bit_21&#45;&gt;_Counter_Bit_2_Bit_22</title>
-<path fill="none" stroke="#000000" d="M284.0749,-152.9703C306.7818,-146.4366 335,-136.0029 335,-124.5 335,-124.5 335,-124.5 335,-77.5 335,-66.9572 327.7242,-59.3711 318.514,-53.9915"/>
-<polygon fill="#000000" stroke="#000000" points="319.788,-50.7189 309.2652,-49.4854 316.722,-57.0118 319.788,-50.7189"/>
-<text text-anchor="start" x="335" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tk1 &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M264.0749,-152.9703C286.7818,-146.4366 315,-136.0029 315,-124.5 315,-124.5 315,-124.5 315,-77.5 315,-66.9572 307.7242,-59.3711 298.514,-53.9915"/>
+<polygon fill="#000000" stroke="#000000" points="299.788,-50.7189 289.2652,-49.4854 296.722,-57.0118 299.788,-50.7189"/>
+<text text-anchor="start" x="315" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tk1 &#160;&#160;</text>
 </g>
 <!-- _Counter_Bit_1 -->
 <!-- _Counter_Bit_1_initial -->
 <g id="node8" class="node">
 <title>_Counter_Bit_1_initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="83" cy="-265.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="78" cy="-265.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _Counter_Bit_1_Bit_11 -->
 <g id="node10" class="node">
 <title>_Counter_Bit_1_Bit_11</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="111,-178 55,-178 55,-142 111,-142 111,-178"/>
-<text text-anchor="start" x="65.9936" y="-156.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_11</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M67.3333,-143C67.3333,-143 98.6667,-143 98.6667,-143 104.3333,-143 110,-148.6667 110,-154.3333 110,-154.3333 110,-165.6667 110,-165.6667 110,-171.3333 104.3333,-177 98.6667,-177 98.6667,-177 67.3333,-177 67.3333,-177 61.6667,-177 56,-171.3333 56,-165.6667 56,-165.6667 56,-154.3333 56,-154.3333 56,-148.6667 61.6667,-143 67.3333,-143"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="106,-178 50,-178 50,-142 106,-142 106,-178"/>
+<text text-anchor="start" x="60.9936" y="-156.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_11</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M62.3333,-143C62.3333,-143 93.6667,-143 93.6667,-143 99.3333,-143 105,-148.6667 105,-154.3333 105,-154.3333 105,-165.6667 105,-165.6667 105,-171.3333 99.3333,-177 93.6667,-177 93.6667,-177 62.3333,-177 62.3333,-177 56.6667,-177 51,-171.3333 51,-165.6667 51,-165.6667 51,-154.3333 51,-154.3333 51,-148.6667 56.6667,-143 62.3333,-143"/>
 </g>
 <!-- _Counter_Bit_1_initial&#45;&gt;_Counter_Bit_1_Bit_11 -->
 <g id="edge5" class="edge">
 <title>_Counter_Bit_1_initial&#45;&gt;_Counter_Bit_1_Bit_11</title>
-<path fill="none" stroke="#000000" d="M83,-259.8288C83,-255.1736 83,-248.4097 83,-242.5 83,-242.5 83,-242.5 83,-195.5 83,-193.1079 83,-190.6252 83,-188.1342"/>
-<polygon fill="#000000" stroke="#000000" points="86.5001,-188.0597 83,-178.0598 79.5001,-188.0598 86.5001,-188.0597"/>
-<text text-anchor="middle" x="84.3895" y="-216" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M78,-259.8288C78,-255.1736 78,-248.4097 78,-242.5 78,-242.5 78,-242.5 78,-195.5 78,-193.1079 78,-190.6252 78,-188.1342"/>
+<polygon fill="#000000" stroke="#000000" points="81.5001,-188.0597 78,-178.0598 74.5001,-188.0598 81.5001,-188.0597"/>
+<text text-anchor="middle" x="79.3895" y="-216" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _Counter_Bit_1_Bit_12 -->
 <g id="node9" class="node">
 <title>_Counter_Bit_1_Bit_12</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="132,-60 76,-60 76,-24 132,-24 132,-60"/>
-<text text-anchor="start" x="86.9936" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_12</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M88.3333,-25C88.3333,-25 119.6667,-25 119.6667,-25 125.3333,-25 131,-30.6667 131,-36.3333 131,-36.3333 131,-47.6667 131,-47.6667 131,-53.3333 125.3333,-59 119.6667,-59 119.6667,-59 88.3333,-59 88.3333,-59 82.6667,-59 77,-53.3333 77,-47.6667 77,-47.6667 77,-36.3333 77,-36.3333 77,-30.6667 82.6667,-25 88.3333,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="124,-60 68,-60 68,-24 124,-24 124,-60"/>
+<text text-anchor="start" x="78.9936" y="-38.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">Bit_12</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M80.3333,-25C80.3333,-25 111.6667,-25 111.6667,-25 117.3333,-25 123,-30.6667 123,-36.3333 123,-36.3333 123,-47.6667 123,-47.6667 123,-53.3333 117.3333,-59 111.6667,-59 111.6667,-59 80.3333,-59 80.3333,-59 74.6667,-59 69,-53.3333 69,-47.6667 69,-47.6667 69,-36.3333 69,-36.3333 69,-30.6667 74.6667,-25 80.3333,-25"/>
 </g>
 <!-- _Counter_Bit_1_Bit_12&#45;&gt;_Counter_Bit_1_Bit_11 -->
 <g id="edge6" class="edge">
 <title>_Counter_Bit_1_Bit_12&#45;&gt;_Counter_Bit_1_Bit_11</title>
-<path fill="none" stroke="#000000" d="M75.7853,-51.016C64.4439,-56.5586 54,-65.0442 54,-77.5 54,-124.5 54,-124.5 54,-124.5 54,-127.4843 54.6223,-130.3561 55.6845,-133.0842"/>
-<polygon fill="#000000" stroke="#000000" points="52.6759,-134.8731 60.7261,-141.7613 58.7285,-131.3564 52.6759,-134.8731"/>
-<text text-anchor="start" x="54" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.tk0^tk1 &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M67.7524,-55.1838C60.1549,-60.7482 54,-68.1435 54,-77.5 54,-124.5 54,-124.5 54,-124.5 54,-127.3317 54.5305,-130.1061 55.4339,-132.7776"/>
+<polygon fill="#000000" stroke="#000000" points="52.421,-134.5757 60.0562,-141.9211 58.6681,-131.4176 52.421,-134.5757"/>
+<text text-anchor="start" x="54" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tk0^tk1 &#160;&#160;</text>
 </g>
 <!-- _Counter_Bit_1_Bit_11&#45;&gt;_Counter_Bit_1_Bit_12 -->
 <g id="edge7" class="edge">
 <title>_Counter_Bit_1_Bit_11&#45;&gt;_Counter_Bit_1_Bit_12</title>
-<path fill="none" stroke="#000000" d="M111.3209,-155.7321C128.837,-151.3027 148,-142.3727 148,-124.5 148,-124.5 148,-124.5 148,-77.5 148,-70.6416 144.7219,-64.8825 139.9553,-60.1334"/>
-<polygon fill="#000000" stroke="#000000" points="142.1174,-57.3809 132.115,-53.8878 137.7559,-62.8561 142.1174,-57.3809"/>
-<text text-anchor="start" x="148" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.tk0 &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M106.2431,-154.4378C121.8052,-149.5506 138,-140.5975 138,-124.5 138,-124.5 138,-124.5 138,-77.5 138,-71.506 135.474,-66.3169 131.661,-61.8984"/>
+<polygon fill="#000000" stroke="#000000" points="134.009,-59.3028 124.2476,-55.1838 129.3098,-64.491 134.009,-59.3028"/>
+<text text-anchor="start" x="138" y="-98" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tk0 &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 22 - 24
test/test_files/day_atlee/statechart_fig8_counter.xml

@@ -8,31 +8,29 @@
   <datamodel>
   </datamodel>
 
-  <tree>
-    <state>
-      <parallel id="Counter">
-        <state id="Bit_1" initial="Bit_11">
-          <state id="Bit_11">
-            <transition port="in" event="tk0" target="../Bit_12"/>
-          </state>
-          <state id="Bit_12">
-            <transition port="in" event="tk0" target="../Bit_11">
-              <raise event="tk1"/>
-            </transition>
-          </state>
+  <root>
+    <parallel id="Counter">
+      <state id="Bit_1" initial="Bit_11">
+        <state id="Bit_11">
+          <transition port="in" event="tk0" target="../Bit_12"/>
         </state>
+        <state id="Bit_12">
+          <transition port="in" event="tk0" target="../Bit_11">
+            <raise event="tk1"/>
+          </transition>
+        </state>
+      </state>
 
-        <state id="Bit_2" initial="Bit_21">
-          <state id="Bit_21">
-            <transition event="tk1" target="../Bit_22"/>
-          </state>
-          <state id="Bit_22">
-            <transition event="tk1" target="../Bit_21">
-              <raise port="out" event="done"/>
-            </transition>
-          </state>
+      <state id="Bit_2" initial="Bit_21">
+        <state id="Bit_21">
+          <transition event="tk1" target="../Bit_22"/>
+        </state>
+        <state id="Bit_22">
+          <transition event="tk1" target="../Bit_21">
+            <raise port="out" event="done"/>
+          </transition>
         </state>
-      </parallel>
-    </state>
-  </tree>
+      </state>
+    </parallel>
+  </root>
 </statechart>

+ 1 - 2
test/test_files/day_atlee/test_01_dialer_takemany.xml

@@ -5,8 +5,7 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="dial" time="0 d">
-    </input_event>
+    <event port="in" name="dial" time="0 d"/>
   </input>
 
   <output>

+ 1 - 2
test/test_files/day_atlee/test_01_dialer_takeone.xml

@@ -5,8 +5,7 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="dial" time="0 d">
-    </input_event>
+    <event port="in" name="dial" time="0 d"/>
   </input>
 
   <output>

+ 4 - 4
test/test_files/day_atlee/test_02_counter_takeone.xml

@@ -5,10 +5,10 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
   </input>
 
   <output>

+ 4 - 4
test/test_files/day_atlee/test_06_counter_lifeline.xml

@@ -7,10 +7,10 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
-    <input_event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
+    <event port="in" name="tk0" time="0 d"/>
   </input>
 
   <output>

+ 1 - 1
test/test_files/day_atlee/test_07_redialer_same.xml

@@ -6,7 +6,7 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="redial" time="0 d"/>
+    <event port="in" name="redial" time="0 d"/>
   </input>
 
   <output>

+ 6 - 8
test/test_files/features/after/fail_duration_type.xml

@@ -5,15 +5,13 @@
     <semantics
         big_step_maximality="*"
         combo_step_maximality="*"/>
-    <tree>
-      <state initial="s1">
-        <state id="s1">
-          <!-- '100' is not a duration -->
-          <transition after="100" target="/s2"/>
-        </state>
-        <state id="s2"/>
+    <root initial="s1">
+      <state id="s1">
+        <!-- '100' is not a duration -->
+        <transition after="100" target="/s2"/>
       </state>
-    </tree>
+      <state id="s2"/>
+    </root>
   </statechart>
   <output/>
 </test>

+ 21 - 23
test/test_files/features/after/test_after.xml

@@ -5,30 +5,28 @@
     <semantics
         big_step_maximality="take_one, take_many"
         combo_step_maximality="*"/>
-    <tree>
-      <state initial="s1">
-        <state id="s1">
-          <transition after="100 ms" target="/s2"/>
-          <transition after="200 ms" target="/s3"/>
-        </state>
-        <state id="s2">
-          <onentry>
-            <raise event="in_2" port="out" />
-          </onentry>
-          <transition after="150 ms" target="/s4"/>
-        </state>
-        <state id="s3">
-          <onentry>
-            <raise event="in_3" port="out"/>
-          </onentry>
-        </state>
-        <state id="s4">
-          <onentry>
-            <raise event="in_4" port="out"/>
-          </onentry>
-        </state>
+    <root initial="s1">
+      <state id="s1">
+        <transition after="100 ms" target="/s2"/>
+        <transition after="200 ms" target="/s3"/>
       </state>
-    </tree>
+      <state id="s2">
+        <onentry>
+          <raise event="in_2" port="out" />
+        </onentry>
+        <transition after="150 ms" target="/s4"/>
+      </state>
+      <state id="s3">
+        <onentry>
+          <raise event="in_3" port="out"/>
+        </onentry>
+      </state>
+      <state id="s4">
+        <onentry>
+          <raise event="in_4" port="out"/>
+        </onentry>
+      </state>
+    </root>
   </statechart>
   <output>
     <big_step>

+ 25 - 27
test/test_files/features/after/test_after_reentry.xml

@@ -4,35 +4,33 @@
     <semantics
         big_step_maximality="take_many"
         combo_step_maximality="combo_take_one"/>
-    <tree>
-      <state>
-        <parallel id="p">
-          <state id="o0" initial="a">
-            <state id="a">
-              <transition after="100 ms" cond='INSTATE(["/p/o1/x"])' target="../b"/>
-              <transition after="150 ms" target="../c"/>
-            </state>
-            <state id="b">
-              <onentry>
-                <raise event="in_b" port="out"/>
-              </onentry>
-              <transition target="../a"/>
-            </state>
-            <state id="c">
-              <onentry>
-                <raise event="in_c" port="out"/>
-              </onentry>
-            </state>
+    <root>
+      <parallel id="p">
+        <state id="o0" initial="a">
+          <state id="a">
+            <transition after="100 ms" cond='INSTATE(["/p/o1/x"])' target="../b"/>
+            <transition after="150 ms" target="../c"/>
           </state>
-          <state id="o1" initial="x">
-            <state id="x">
-              <transition after="250 ms" target="../y"/>
-            </state>
-            <state id="y"/>
+          <state id="b">
+            <onentry>
+              <raise event="in_b" port="out"/>
+            </onentry>
+            <transition target="../a"/>
           </state>
-        </parallel>
-      </state>
-    </tree>
+          <state id="c">
+            <onentry>
+              <raise event="in_c" port="out"/>
+            </onentry>
+          </state>
+        </state>
+        <state id="o1" initial="x">
+          <state id="x">
+            <transition after="250 ms" target="../y"/>
+          </state>
+          <state id="y"/>
+        </state>
+      </parallel>
+    </root>
   </statechart>
   <output>
     <big_step>

+ 9 - 11
test/test_files/features/datamodel/fail_static_types.xml

@@ -7,18 +7,16 @@
       <var id="x" expr="5"/>
     </datamodel>
 
-    <tree>
-      <state initial="a">
-        <state id="a">
-          <onentry>
-            <code>
-              greeting = "hello";
-              x = greeting; <!-- 'x' is already declared as integer at instance level -->
-            </code>
-          </onentry>
-        </state>
+    <root initial="a">
+      <state id="a">
+        <onentry>
+          <code>
+            greeting = "hello";
+            x = greeting; <!-- 'x' is already declared as integer at instance level -->
+          </code>
+        </onentry>
       </state>
-    </tree>
+    </root>
   </statechart>
 
   <output>

+ 1 - 3
test/test_files/features/datamodel/fail_unique_var.xml

@@ -10,9 +10,7 @@
       <var id="x" expr="43"/>
     </datamodel>
 
-    <tree>
-      <state/>
-    </tree>
+    <root/>
   </statechart>
 
   <output>

+ 8 - 10
test/test_files/features/datamodel/test_cond.xml

@@ -6,19 +6,17 @@
       <var id="x" expr="42"/>
       <!-- <var id="y" expr="x"/>this is allowed, value of x copied to y -->
     </datamodel>
-    <tree>
-      <state initial="start">
-        <state id="start">
-          <transition event="e" port="in" target="/done" cond="x == 42">
-            <raise event="done" port="out"/>
-          </transition>
-        </state>
-        <state id="done"/>
+    <root initial="start">
+      <state id="start">
+        <transition event="e" port="in" target="/done" cond="x == 42">
+          <raise event="done" port="out"/>
+        </transition>
       </state>
-    </tree>
+      <state id="done"/>
+    </root>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 4 - 4
test/test_files/features/datamodel/test_guard_action.svg

@@ -4,11 +4,11 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="263pt" height="157pt"
- viewBox="0.00 0.00 263.00 157.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="260pt" height="157pt"
+ viewBox="0.00 0.00 260.00 157.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 153)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-153 259,-153 259,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-153 256,-153 256,4 -4,4"/>
 <!-- __initial -->
 <g id="node1" class="node">
 <title>__initial</title>
@@ -56,7 +56,7 @@
 <title>_counting&#45;&gt;_counting</title>
 <path fill="none" stroke="#000000" d="M89.2372,-97.443C112.4222,-99.0331 135.453,-97.2188 135.453,-92 135.453,-87.5559 118.752,-85.5806 99.4768,-86.074"/>
 <polygon fill="#000000" stroke="#000000" points="99.0611,-82.5896 89.2372,-86.557 99.391,-89.5818 99.0611,-82.5896"/>
-<text text-anchor="start" x="135.453" y="-89" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[x &lt; 3]/x += 1 &#160;^out.inc &#160;&#160;</text>
+<text text-anchor="start" x="135.453" y="-89" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[x &lt; 3]/x += 1 ^out.inc &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 13 - 15
test/test_files/features/datamodel/test_guard_action.xml

@@ -7,24 +7,22 @@
       <var id="x" expr="0"/>
       <!-- <var id="y" expr="x"/>this is allowed, y is also 0 -->
     </datamodel>
-    <tree>
-      <state initial="counting">
-        <state id="counting">
-          <transition event="e" port="in" target="."/>
-          <transition cond="x &lt; 3" target=".">
-            <code> x += 1; </code>
-            <raise event="inc" port="out"/>
-          </transition>
-          <transition cond="x == 3" target="../done"/>
-        </state>
-        <state id="done">
-          <onentry><raise event="done" port="out"/></onentry>
-        </state>
+    <root initial="counting">
+      <state id="counting">
+        <transition event="e" port="in" target="."/>
+        <transition cond="x &lt; 3" target=".">
+          <code> x += 1; </code>
+          <raise event="inc" port="out"/>
+        </transition>
+        <transition cond="x == 3" target="../done"/>
       </state>
-    </tree>
+      <state id="done">
+        <onentry><raise event="done" port="out"/></onentry>
+      </state>
+    </root>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 65 - 67
test/test_files/features/expressions/test_expressions.xml

@@ -2,84 +2,82 @@
 <test>
   <statechart>
     <semantics big_step_maximality="take_many"/>
-    <tree>
-      <state initial="comparisons">
+    <root initial="comparisons">
 
-        <state id="comparisons" initial="s1">
-          <transition event="e" target="." port="in"/>
-          <state id="s1">
-            <transition cond="1 == 1" target="../s2"/>
-          </state>
-          <state id="s2">
-            <transition cond="1 != 2" target="../s3"/>
-          </state>
-          <state id="s3">
-            <transition cond="1 &lt; 2" target="../s4"/>
-          </state>
-          <state id="s4">
-            <transition cond="2 &gt; 1" target="../s5"/>
-          </state>
-          <state id="s5">
-            <transition target="/arithmetic"/>
-          </state>
+      <state id="comparisons" initial="s1">
+        <transition event="e" target="." port="in"/>
+        <state id="s1">
+          <transition cond="1 == 1" target="../s2"/>
         </state>
-
-        <state id="arithmetic" initial="s1">
-          <state id="s1">
-            <transition cond="1 + 1 == 2" target="../s2"/>
-          </state>
-          <state id="s2">
-            <transition cond="42 == 52 - 11 + 1" target="../s3"/>
-          </state>
-          <state id="s3">
-            <transition cond="2 * 3 == 6" target="../s4"/>
-          </state>
-          <state id="s4">
-            <transition cond="21 / 3 == 7" target="../s5"/>
-          </state>
-          <state id="s5">
-            <transition cond="256 == 2 ** 2 ** 3" target="../s6"/>
-          </state>
-          <state id="s6">
-            <transition cond="5 % 2 == 1" target="../s7"/>
-          </state>
-          <state id="s7">
-            <transition target="/boolean_logic"/>
-          </state>
+        <state id="s2">
+          <transition cond="1 != 2" target="../s3"/>
+        </state>
+        <state id="s3">
+          <transition cond="1 &lt; 2" target="../s4"/>
+        </state>
+        <state id="s4">
+          <transition cond="2 &gt; 1" target="../s5"/>
         </state>
+        <state id="s5">
+          <transition target="/arithmetic"/>
+        </state>
+      </state>
 
-        <state id="boolean_logic" initial="s1">
-          <state id="s1">
-            <transition cond="True" target="../s2"/>
-          </state>
-          <state id="s2">
-            <transition cond="False or True" target="../s3"/>
-          </state>
-          <state id="s3">
-            <transition cond="True and not False" target="../s4"/>
-          </state>
-          <state id="s4">
-            <transition cond="not (True and False or False)" target="../s5"/>
-          </state>
-          <state id="s5">
-            <transition cond="not (False or False and True)" target="../s6"/>
-          </state>
-          <state id="s6">
-            <transition target="/final"/>
-          </state>
+      <state id="arithmetic" initial="s1">
+        <state id="s1">
+          <transition cond="1 + 1 == 2" target="../s2"/>
+        </state>
+        <state id="s2">
+          <transition cond="42 == 52 - 11 + 1" target="../s3"/>
+        </state>
+        <state id="s3">
+          <transition cond="2 * 3 == 6" target="../s4"/>
+        </state>
+        <state id="s4">
+          <transition cond="21 / 3 == 7" target="../s5"/>
+        </state>
+        <state id="s5">
+          <transition cond="256 == 2 ** 2 ** 3" target="../s6"/>
+        </state>
+        <state id="s6">
+          <transition cond="5 % 2 == 1" target="../s7"/>
         </state>
+        <state id="s7">
+          <transition target="/boolean_logic"/>
+        </state>
+      </state>
 
-        <state id="final">
-          <onentry>
-            <raise event="all_good" port="out"/>
-          </onentry>
+      <state id="boolean_logic" initial="s1">
+        <state id="s1">
+          <transition cond="True" target="../s2"/>
+        </state>
+        <state id="s2">
+          <transition cond="False or True" target="../s3"/>
+        </state>
+        <state id="s3">
+          <transition cond="True and not False" target="../s4"/>
+        </state>
+        <state id="s4">
+          <transition cond="not (True and False or False)" target="../s5"/>
         </state>
+        <state id="s5">
+          <transition cond="not (False or False and True)" target="../s6"/>
+        </state>
+        <state id="s6">
+          <transition target="/final"/>
+        </state>
+      </state>
 
+      <state id="final">
+        <onentry>
+          <raise event="all_good" port="out"/>
+        </onentry>
       </state>
-    </tree>
+
+    </root>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 69 - 71
test/test_files/features/expressions/test_expressions_ortho.xml

@@ -2,88 +2,86 @@
 <test>
   <statechart>
     <semantics/>
-    <tree>
-      <state>
+    <root>
 
-        <parallel id="p">
-          <transition event="e" port="in" target="."/>
+      <parallel id="p">
+        <transition event="e" port="in" target="."/>
 
-          <state id="comparisons" initial="s1">
-            <state id="s1">
-              <transition cond="1 == 1" target="../s2"/>
-            </state>
-            <state id="s2">
-              <transition cond="1 != 2" target="../s3"/>
-            </state>
-            <state id="s3">
-              <transition cond="1 &lt; 2" target="../s4"/>
-            </state>
-            <state id="s4">
-              <transition cond="2 &gt; 1" target="../ok"/>
-            </state>
-            <state id="ok">
-              <onentry>
-                <raise event="ok" port="out"/>
-              </onentry>
-            </state>
+        <state id="comparisons" initial="s1">
+          <state id="s1">
+            <transition cond="1 == 1" target="../s2"/>
           </state>
+          <state id="s2">
+            <transition cond="1 != 2" target="../s3"/>
+          </state>
+          <state id="s3">
+            <transition cond="1 &lt; 2" target="../s4"/>
+          </state>
+          <state id="s4">
+            <transition cond="2 &gt; 1" target="../ok"/>
+          </state>
+          <state id="ok">
+            <onentry>
+              <raise event="ok" port="out"/>
+            </onentry>
+          </state>
+        </state>
 
-          <state id="arithmetic" initial="s1">
-            <state id="s1">
-              <transition cond="1 + 1 == 2" target="../s2"/>
-            </state>
-            <state id="s2">
-              <transition cond="42 == 52 - 11 + 1" target="../s3"/>
-            </state>
-            <state id="s3">
-              <transition cond="2 * 3 == 6" target="../s4"/>
-            </state>
-            <state id="s4">
-              <transition cond="21 / 3 == 7" target="../s5"/>
-            </state>
-            <state id="s5">
-              <transition cond="256 == 2 ** 2 ** 3" target="../s6"/>
-            </state>
-            <state id="s6">
-              <transition cond="5 % 2 == 1" target="../ok"/>
-            </state>
-            <state id="ok">
-              <onentry>
-                <raise event="ok" port="out"/>
-              </onentry>
-            </state>
+        <state id="arithmetic" initial="s1">
+          <state id="s1">
+            <transition cond="1 + 1 == 2" target="../s2"/>
+          </state>
+          <state id="s2">
+            <transition cond="42 == 52 - 11 + 1" target="../s3"/>
+          </state>
+          <state id="s3">
+            <transition cond="2 * 3 == 6" target="../s4"/>
+          </state>
+          <state id="s4">
+            <transition cond="21 / 3 == 7" target="../s5"/>
+          </state>
+          <state id="s5">
+            <transition cond="256 == 2 ** 2 ** 3" target="../s6"/>
           </state>
+          <state id="s6">
+            <transition cond="5 % 2 == 1" target="../ok"/>
+          </state>
+          <state id="ok">
+            <onentry>
+              <raise event="ok" port="out"/>
+            </onentry>
+          </state>
+        </state>
 
-          <state id="boolean_logic" initial="s1">
-            <state id="s1">
-              <transition cond="True" target="../s2"/>
-            </state>
-            <state id="s2">
-              <transition cond="False or True" target="../s3"/>
-            </state>
-            <state id="s3">
-              <transition cond="True and not False" target="../s4"/>
-            </state>
-            <state id="s4">
-              <transition cond="not (True and False or False)" target="../s5"/>
-            </state>
-            <state id="s5">
-              <transition cond="not (False or False and True)" target="../ok"/>
-            </state>
-            <state id="ok">
-              <onentry>
-                <raise event="ok" port="out"/>
-              </onentry>
-            </state>
+        <state id="boolean_logic" initial="s1">
+          <state id="s1">
+            <transition cond="True" target="../s2"/>
+          </state>
+          <state id="s2">
+            <transition cond="False or True" target="../s3"/>
+          </state>
+          <state id="s3">
+            <transition cond="True and not False" target="../s4"/>
+          </state>
+          <state id="s4">
+            <transition cond="not (True and False or False)" target="../s5"/>
+          </state>
+          <state id="s5">
+            <transition cond="not (False or False and True)" target="../ok"/>
+          </state>
+          <state id="ok">
+            <onentry>
+              <raise event="ok" port="out"/>
+            </onentry>
           </state>
+        </state>
 
-        </parallel>
+      </parallel>
 
-      </state>
-    </tree>
+    </root>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 9 - 11
test/test_files/features/functions/fail_parameter_type.xml

@@ -17,17 +17,15 @@
       </func>
     </datamodel>
 
-    <tree>
-      <state initial="ready">
-        <state id="ready">
-          <!-- illegal condition: sole parameter of numdigits is 'int', however string is given -->
-          <transition port="in" event="start" target="../final" cond='numdigits("123") == 3'>
-            <raise port="out" event="ok"/>
-          </transition>
-        </state>
-
-        <state id="final"/>
+    <root initial="ready">
+      <state id="ready">
+        <!-- illegal condition: sole parameter of numdigits is 'int', however string is given -->
+        <transition port="in" event="start" target="../final" cond='numdigits("123") == 3'>
+          <raise port="out" event="ok"/>
+        </transition>
       </state>
-    </tree>
+
+      <state id="final"/>
+    </root>
   </statechart>
 </test>

+ 9 - 11
test/test_files/features/functions/fail_return_type.xml

@@ -17,17 +17,15 @@
       </func>
     </datamodel>
 
-    <tree>
-      <state initial="ready">
-        <state id="ready">
-          <!-- illegal condition: return type of numdigits inferred to be 'int', however RHS of '=='-expression is string -->
-          <transition port="in" event="start" target="../final" cond='numdigits(123) == "3"'>
-            <raise port="out" event="ok"/>
-          </transition>
-        </state>
-
-        <state id="final"/>
+    <root initial="ready">
+      <state id="ready">
+        <!-- illegal condition: return type of numdigits inferred to be 'int', however RHS of '=='-expression is string -->
+        <transition port="in" event="start" target="../final" cond='numdigits(123) == "3"'>
+          <raise port="out" event="ok"/>
+        </transition>
       </state>
-    </tree>
+
+      <state id="final"/>
+    </root>
   </statechart>
 </test>

+ 46 - 0
test/test_files/features/functions/test_functions.svg

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.40.1 (20161225.0304)
+ -->
+<!-- Title: state transitions Pages: 1 -->
+<svg width="299pt" height="147pt"
+ viewBox="0.00 0.00 298.55 147.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 143)">
+<title>state transitions</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-143 294.551,-143 294.551,4 -4,4"/>
+<!-- __initial -->
+<g id="node1" class="node">
+<title>__initial</title>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="28" cy="-133.5" rx="5.5" ry="5.5"/>
+</g>
+<!-- _ready -->
+<g id="node3" class="node">
+<title>_ready</title>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="56,-100 0,-100 0,-64 56,-64 56,-100"/>
+<text text-anchor="start" x="12.9964" y="-78.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">ready</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M12.3333,-65C12.3333,-65 43.6667,-65 43.6667,-65 49.3333,-65 55,-70.6667 55,-76.3333 55,-76.3333 55,-87.6667 55,-87.6667 55,-93.3333 49.3333,-99 43.6667,-99 43.6667,-99 12.3333,-99 12.3333,-99 6.6667,-99 1,-93.3333 1,-87.6667 1,-87.6667 1,-76.3333 1,-76.3333 1,-70.6667 6.6667,-65 12.3333,-65"/>
+</g>
+<!-- __initial&#45;&gt;_ready -->
+<g id="edge1" class="edge">
+<title>__initial&#45;&gt;_ready</title>
+<path fill="none" stroke="#000000" d="M28,-127.9886C28,-123.6293 28,-117.1793 28,-110.4801"/>
+<polygon fill="#000000" stroke="#000000" points="31.5001,-110.0122 28,-100.0122 24.5001,-110.0122 31.5001,-110.0122"/>
+<text text-anchor="middle" x="29.3895" y="-111" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+</g>
+<!-- _final -->
+<g id="node2" class="node">
+<title>_final</title>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="56,-36 0,-36 0,0 56,0 56,-36"/>
+<text text-anchor="start" x="16.999" y="-14.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">final</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M12.3333,-1C12.3333,-1 43.6667,-1 43.6667,-1 49.3333,-1 55,-6.6667 55,-12.3333 55,-12.3333 55,-23.6667 55,-23.6667 55,-29.3333 49.3333,-35 43.6667,-35 43.6667,-35 12.3333,-35 12.3333,-35 6.6667,-35 1,-29.3333 1,-23.6667 1,-23.6667 1,-12.3333 1,-12.3333 1,-6.6667 6.6667,-1 12.3333,-1"/>
+</g>
+<!-- _ready&#45;&gt;_final -->
+<g id="edge2" class="edge">
+<title>_ready&#45;&gt;_final</title>
+<path fill="none" stroke="#000000" d="M28,-63.8314C28,-58.4728 28,-52.4735 28,-46.6262"/>
+<polygon fill="#000000" stroke="#000000" points="31.5001,-46.4363 28,-36.4363 24.5001,-46.4363 31.5001,-46.4363"/>
+<text text-anchor="start" x="28" y="-47" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.start [numdigits(123) == 3 and digit(123,1) == 2]^out.ok &#160;&#160;</text>
+</g>
+</g>
+</svg>

+ 10 - 12
test/test_files/features/functions/test_functions.xml

@@ -17,22 +17,20 @@
       </func>
     </datamodel>
 
-    <tree>
-      <state initial="ready">
-        <state id="ready">
-          <transition port="in" event="start" target="../final"
-            cond="numdigits(123) == 3 and digit(123, 1) == 2">
-            <raise port="out" event="ok"/>
-          </transition>
-        </state>
-
-        <state id="final"/>
+    <root initial="ready">
+      <state id="ready">
+        <transition port="in" event="start" target="../final"
+          cond="numdigits(123) == 3 and digit(123, 1) == 2">
+          <raise port="out" event="ok"/>
+        </transition>
       </state>
-    </tree>
+
+      <state id="final"/>
+    </root>
   </statechart>
 
   <input>
-    <input_event port="in" name="start" time="0 d"/>
+    <event port="in" name="start" time="0 d"/>
   </input>
 
   <output>

+ 1 - 1
test/test_files/semantics/big_step_maximality/statechart_flat.svg

@@ -58,7 +58,7 @@
 <title>_a&#45;&gt;_b</title>
 <path fill="none" stroke="#000000" d="M53,-147.8711C53,-142.4482 53,-136.3229 53,-130.2494"/>
 <polygon fill="#000000" stroke="#000000" points="56.5001,-130.21 53,-120.21 49.5001,-130.21 56.5001,-130.21"/>
-<text text-anchor="start" x="53" y="-131" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<text text-anchor="start" x="53" y="-131" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 15 - 17
test/test_files/semantics/big_step_maximality/statechart_flat.xml

@@ -2,22 +2,20 @@
 <statechart>
   <semantics/>
   <datamodel/>
-  <tree>
-    <state initial="a">
-      <state id="a">
-        <transition event="e" target="/b" port="in"/>
-      </state>
-      <state id="b">
-        <onentry>
-          <raise event="in_b" port="out"/>
-        </onentry>
-        <transition target="/c"/>
-      </state>
-      <state id="c">
-        <onentry>
-          <raise event="in_c" port="out"/>
-        </onentry>
-      </state>
+  <root initial="a">
+    <state id="a">
+      <transition event="e" target="/b" port="in"/>
     </state>
-  </tree>
+    <state id="b">
+      <onentry>
+        <raise event="in_b" port="out"/>
+      </onentry>
+      <transition target="/c"/>
+    </state>
+    <state id="c">
+      <onentry>
+        <raise event="in_c" port="out"/>
+      </onentry>
+    </state>
+  </root>
 </statechart>

+ 1 - 1
test/test_files/semantics/big_step_maximality/statechart_ortho.svg

@@ -139,7 +139,7 @@
 <title>_p_o0_a&#45;&gt;_p_o0_b</title>
 <path fill="none" stroke="#000000" d="M85,-279.9402C85,-274.3497 85,-268.1701 85,-262.5 85,-262.5 85,-262.5 85,-215.5 85,-213.127 85,-210.6757 85,-208.2081"/>
 <polygon fill="#000000" stroke="#000000" points="88.5001,-208.1306 85,-198.1306 81.5001,-208.1306 88.5001,-208.1306"/>
-<text text-anchor="start" x="85" y="-236" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<text text-anchor="start" x="85" y="-236" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 34 - 36
test/test_files/semantics/big_step_maximality/statechart_ortho.xml

@@ -2,42 +2,40 @@
 <statechart>
   <semantics/>
   <datamodel/>
-  <tree>
-    <state>
-      <parallel id="p">
-        <state id="o0" initial="a">
-          <state id="a">
-            <transition event="e" port="in" target="../b"/>
-          </state>
-          <state id="b">
-            <onentry>
-              <raise event="in_b" port="out"/>
-            </onentry>
-            <transition target="../c"/>
-          </state>
-          <state id="c">
-            <onentry>
-              <raise event="in_c" port="out"/>
-            </onentry>
-          </state>
+  <root>
+    <parallel id="p">
+      <state id="o0" initial="a">
+        <state id="a">
+          <transition event="e" port="in" target="../b"/>
         </state>
-        <state id="o1" initial="d">
-          <state id="d">
-            <transition target="../e"/>
-          </state>
-          <state id="e">
-            <onentry>
-              <raise event="in_e" port="out"/>
-            </onentry>
-            <transition target="../f"/>
-          </state>
-          <state id="f">
-            <onentry>
-              <raise event="in_f" port="out"/>
-            </onentry>
-          </state>
+        <state id="b">
+          <onentry>
+            <raise event="in_b" port="out"/>
+          </onentry>
+          <transition target="../c"/>
         </state>
-      </parallel>
-    </state>
-  </tree>
+        <state id="c">
+          <onentry>
+            <raise event="in_c" port="out"/>
+          </onentry>
+        </state>
+      </state>
+      <state id="o1" initial="d">
+        <state id="d">
+          <transition target="../e"/>
+        </state>
+        <state id="e">
+          <onentry>
+            <raise event="in_e" port="out"/>
+          </onentry>
+          <transition target="../f"/>
+        </state>
+        <state id="f">
+          <onentry>
+            <raise event="in_f" port="out"/>
+          </onentry>
+        </state>
+      </state>
+    </parallel>
+  </root>
 </statechart>

+ 23 - 25
test/test_files/semantics/big_step_maximality/test_flat_syntactic.xml

@@ -5,35 +5,33 @@
       big_step_maximality="syntactic"
       input_event_lifeline="whole"/>
     <datamodel/>
-    <tree>
-      <state initial="a">
-        <state id="a">
-          <transition port="in" event="e" target="/b"/>
-        </state>
-        <state id="b" stable="true">
-          <onentry>
-            <raise event="in_b" port="out"/>
-          </onentry>
-          <transition port="in" event="e" target="/c"/>
-        </state>
-        <state id="c">
-          <onentry>
-            <raise event="in_c" port="out"/>
-          </onentry>
-          <transition port="in" event="e" target="/d"/>
-        </state>
-        <state id="d" stable="true">
-          <onentry>
-            <raise event="in_d" port="out"/>
-          </onentry>
-        </state>
+    <root initial="a">
+      <state id="a">
+        <transition port="in" event="e" target="/b"/>
       </state>
-    </tree>
+      <state id="b" stable="true">
+        <onentry>
+          <raise event="in_b" port="out"/>
+        </onentry>
+        <transition port="in" event="e" target="/c"/>
+      </state>
+      <state id="c">
+        <onentry>
+          <raise event="in_c" port="out"/>
+        </onentry>
+        <transition port="in" event="e" target="/d"/>
+      </state>
+      <state id="d" stable="true">
+        <onentry>
+          <raise event="in_d" port="out"/>
+        </onentry>
+      </state>
+    </root>
   </statechart>
 
   <input>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
   </input>
 
   <output>

+ 1 - 1
test/test_files/semantics/big_step_maximality/test_flat_takemany.xml

@@ -5,7 +5,7 @@
       big_step_maximality="take_many"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/big_step_maximality/test_flat_takeone.xml

@@ -5,7 +5,7 @@
       big_step_maximality="take_one"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 71 - 71
test/test_files/semantics/big_step_maximality/test_ortho_syntactic.svg

@@ -4,25 +4,25 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="300pt" height="660pt"
- viewBox="0.00 0.00 300.00 660.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="260pt" height="660pt"
+ viewBox="0.00 0.00 260.00 660.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 656)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-656 296,-656 296,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-656 256,-656 256,4 -4,4"/>
 <g id="clust1" class="cluster">
 <title>cluster__p</title>
-<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 272,-8 272,-8 278,-8 284,-14 284,-20 284,-20 284,-601 284,-601 284,-607 278,-613 272,-613 272,-613 20,-613 20,-613 14,-613 8,-607 8,-601 8,-601 8,-20 8,-20 8,-14 14,-8 20,-8"/>
-<text text-anchor="start" x="142.6646" y="-594.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">p</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 232,-8 232,-8 238,-8 244,-14 244,-20 244,-20 244,-601 244,-601 244,-607 238,-613 232,-613 232,-613 20,-613 20,-613 14,-613 8,-607 8,-601 8,-601 8,-20 8,-20 8,-14 14,-8 20,-8"/>
+<text text-anchor="start" x="122.6646" y="-594.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">p</text>
 </g>
 <g id="clust2" class="cluster">
 <title>cluster__p_ortho1</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="154,-16 154,-575 276,-575 276,-16 154,-16"/>
-<text text-anchor="start" x="197.9936" y="-556.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">ortho1</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="134,-16 134,-575 236,-575 236,-16 134,-16"/>
+<text text-anchor="start" x="167.9936" y="-556.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">ortho1</text>
 </g>
 <g id="clust3" class="cluster">
 <title>cluster__p_ortho0</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-16 24,-575 146,-575 146,-16 24,-16"/>
-<text text-anchor="start" x="67.9936" y="-556.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">ortho0</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-16 24,-575 126,-575 126,-16 24,-16"/>
+<text text-anchor="start" x="57.9936" y="-556.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">ortho0</text>
 </g>
 <!-- __initial -->
 <g id="node1" class="node">
@@ -41,137 +41,137 @@
 <!-- _p_ortho1_initial -->
 <g id="node4" class="node">
 <title>_p_ortho1_initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="215" cy="-531.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="185" cy="-531.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _p_ortho1_e -->
 <g id="node8" class="node">
 <title>_p_ortho1_e</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="243,-444 187,-444 187,-408 243,-408 243,-444"/>
-<text text-anchor="start" x="211.6646" y="-422.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">e</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M199.3333,-409C199.3333,-409 230.6667,-409 230.6667,-409 236.3333,-409 242,-414.6667 242,-420.3333 242,-420.3333 242,-431.6667 242,-431.6667 242,-437.3333 236.3333,-443 230.6667,-443 230.6667,-443 199.3333,-443 199.3333,-443 193.6667,-443 188,-437.3333 188,-431.6667 188,-431.6667 188,-420.3333 188,-420.3333 188,-414.6667 193.6667,-409 199.3333,-409"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="213,-444 157,-444 157,-408 213,-408 213,-444"/>
+<text text-anchor="start" x="181.6646" y="-422.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">e</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M169.3333,-409C169.3333,-409 200.6667,-409 200.6667,-409 206.3333,-409 212,-414.6667 212,-420.3333 212,-420.3333 212,-431.6667 212,-431.6667 212,-437.3333 206.3333,-443 200.6667,-443 200.6667,-443 169.3333,-443 169.3333,-443 163.6667,-443 158,-437.3333 158,-431.6667 158,-431.6667 158,-420.3333 158,-420.3333 158,-414.6667 163.6667,-409 169.3333,-409"/>
 </g>
 <!-- _p_ortho1_initial&#45;&gt;_p_ortho1_e -->
 <g id="edge2" class="edge">
 <title>_p_ortho1_initial&#45;&gt;_p_ortho1_e</title>
-<path fill="none" stroke="#000000" d="M215,-525.8288C215,-521.1736 215,-514.4097 215,-508.5 215,-508.5 215,-508.5 215,-461.5 215,-459.1079 215,-456.6252 215,-454.1342"/>
-<polygon fill="#000000" stroke="#000000" points="218.5001,-454.0597 215,-444.0598 211.5001,-454.0598 218.5001,-454.0597"/>
-<text text-anchor="middle" x="216.3895" y="-482" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M185,-525.8288C185,-521.1736 185,-514.4097 185,-508.5 185,-508.5 185,-508.5 185,-461.5 185,-459.1079 185,-456.6252 185,-454.1342"/>
+<polygon fill="#000000" stroke="#000000" points="188.5001,-454.0597 185,-444.0598 181.5001,-454.0598 188.5001,-454.0597"/>
+<text text-anchor="middle" x="186.3895" y="-482" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _p_ortho1_h -->
 <g id="node5" class="node">
 <title>_p_ortho1_h</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="268,-70 162,-70 162,-24 268,-24 268,-70"/>
-<text text-anchor="start" x="204.995" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">h ✓</text>
-<text text-anchor="start" x="167.5022" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.in_d</text>
-<polygon fill="#000000" stroke="#000000" points="162,-47 162,-47 268,-47 268,-47 162,-47"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M175,-25C175,-25 255,-25 255,-25 261,-25 267,-31 267,-37 267,-37 267,-57 267,-57 267,-63 261,-69 255,-69 255,-69 175,-69 175,-69 169,-69 163,-63 163,-57 163,-57 163,-37 163,-37 163,-31 169,-25 175,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="228,-70 142,-70 142,-24 228,-24 228,-70"/>
+<text text-anchor="start" x="174.995" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">h ✓</text>
+<text text-anchor="start" x="147.5078" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^in_h</text>
+<polygon fill="#000000" stroke="#000000" points="142,-47 142,-47 228,-47 228,-47 142,-47"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M155,-25C155,-25 215,-25 215,-25 221,-25 227,-31 227,-37 227,-37 227,-57 227,-57 227,-63 221,-69 215,-69 215,-69 155,-69 155,-69 149,-69 143,-63 143,-57 143,-57 143,-37 143,-37 143,-31 149,-25 155,-25"/>
 </g>
 <!-- _p_ortho1_g -->
 <g id="node6" class="node">
 <title>_p_ortho1_g</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="268,-198 162,-198 162,-152 268,-152 268,-198"/>
-<text text-anchor="start" x="204.995" y="-181.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">g ✓</text>
-<text text-anchor="start" x="167.8376" y="-161.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.in_c</text>
-<polygon fill="#000000" stroke="#000000" points="162,-175 162,-175 268,-175 268,-175 162,-175"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M175,-153C175,-153 255,-153 255,-153 261,-153 267,-159 267,-165 267,-165 267,-185 267,-185 267,-191 261,-197 255,-197 255,-197 175,-197 175,-197 169,-197 163,-191 163,-185 163,-185 163,-165 163,-165 163,-159 169,-153 175,-153"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="228,-198 142,-198 142,-152 228,-152 228,-198"/>
+<text text-anchor="start" x="174.995" y="-181.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">g ✓</text>
+<text text-anchor="start" x="147.5078" y="-161.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^in_g</text>
+<polygon fill="#000000" stroke="#000000" points="142,-175 142,-175 228,-175 228,-175 142,-175"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M155,-153C155,-153 215,-153 215,-153 221,-153 227,-159 227,-165 227,-165 227,-185 227,-185 227,-191 221,-197 215,-197 215,-197 155,-197 155,-197 149,-197 143,-191 143,-185 143,-185 143,-165 143,-165 143,-159 149,-153 155,-153"/>
 </g>
 <!-- _p_ortho1_g&#45;&gt;_p_ortho1_h -->
 <g id="edge3" class="edge">
 <title>_p_ortho1_g&#45;&gt;_p_ortho1_h</title>
-<path fill="none" stroke="#000000" d="M215,-151.8694C215,-146.1895 215,-140.125 215,-134.5 215,-134.5 215,-134.5 215,-87.5 215,-85.127 215,-82.6757 215,-80.2081"/>
-<polygon fill="#000000" stroke="#000000" points="218.5001,-80.1306 215,-70.1306 211.5001,-80.1306 218.5001,-80.1306"/>
-<text text-anchor="start" x="215" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M185,-151.8694C185,-146.1895 185,-140.125 185,-134.5 185,-134.5 185,-134.5 185,-87.5 185,-85.127 185,-82.6757 185,-80.2081"/>
+<polygon fill="#000000" stroke="#000000" points="188.5001,-80.1306 185,-70.1306 181.5001,-80.1306 188.5001,-80.1306"/>
+<text text-anchor="start" x="185" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 <!-- _p_ortho1_f -->
 <g id="node7" class="node">
 <title>_p_ortho1_f</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="268,-326 162,-326 162,-280 268,-280 268,-326"/>
-<text text-anchor="start" x="213.3326" y="-309.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">f</text>
-<text text-anchor="start" x="167.5022" y="-289.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.in_b</text>
-<polygon fill="#000000" stroke="#000000" points="162,-303 162,-303 268,-303 268,-303 162,-303"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M175,-281C175,-281 255,-281 255,-281 261,-281 267,-287 267,-293 267,-293 267,-313 267,-313 267,-319 261,-325 255,-325 255,-325 175,-325 175,-325 169,-325 163,-319 163,-313 163,-313 163,-293 163,-293 163,-287 169,-281 175,-281"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="226.5,-326 143.5,-326 143.5,-280 226.5,-280 226.5,-326"/>
+<text text-anchor="start" x="183.8326" y="-309.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">f</text>
+<text text-anchor="start" x="149.6758" y="-289.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^in_f</text>
+<polygon fill="#000000" stroke="#000000" points="144,-303 144,-303 227,-303 227,-303 144,-303"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M156.5,-281C156.5,-281 213.5,-281 213.5,-281 219.5,-281 225.5,-287 225.5,-293 225.5,-293 225.5,-313 225.5,-313 225.5,-319 219.5,-325 213.5,-325 213.5,-325 156.5,-325 156.5,-325 150.5,-325 144.5,-319 144.5,-313 144.5,-313 144.5,-293 144.5,-293 144.5,-287 150.5,-281 156.5,-281"/>
 </g>
 <!-- _p_ortho1_f&#45;&gt;_p_ortho1_g -->
 <g id="edge4" class="edge">
 <title>_p_ortho1_f&#45;&gt;_p_ortho1_g</title>
-<path fill="none" stroke="#000000" d="M215,-279.8694C215,-274.1895 215,-268.125 215,-262.5 215,-262.5 215,-262.5 215,-215.5 215,-213.127 215,-210.6757 215,-208.2081"/>
-<polygon fill="#000000" stroke="#000000" points="218.5001,-208.1306 215,-198.1306 211.5001,-208.1306 218.5001,-208.1306"/>
-<text text-anchor="start" x="215" y="-236" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M185,-279.8694C185,-274.1895 185,-268.125 185,-262.5 185,-262.5 185,-262.5 185,-215.5 185,-213.127 185,-210.6757 185,-208.2081"/>
+<polygon fill="#000000" stroke="#000000" points="188.5001,-208.1306 185,-198.1306 181.5001,-208.1306 188.5001,-208.1306"/>
+<text text-anchor="start" x="185" y="-236" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 <!-- _p_ortho1_e&#45;&gt;_p_ortho1_f -->
 <g id="edge5" class="edge">
 <title>_p_ortho1_e&#45;&gt;_p_ortho1_f</title>
-<path fill="none" stroke="#000000" d="M215,-407.9402C215,-402.3497 215,-396.1701 215,-390.5 215,-390.5 215,-390.5 215,-343.5 215,-341.127 215,-338.6757 215,-336.2081"/>
-<polygon fill="#000000" stroke="#000000" points="218.5001,-336.1306 215,-326.1306 211.5001,-336.1306 218.5001,-336.1306"/>
-<text text-anchor="start" x="215" y="-364" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M185,-407.9402C185,-402.3497 185,-396.1701 185,-390.5 185,-390.5 185,-390.5 185,-343.5 185,-341.127 185,-338.6757 185,-336.2081"/>
+<polygon fill="#000000" stroke="#000000" points="188.5001,-336.1306 185,-326.1306 181.5001,-336.1306 188.5001,-336.1306"/>
+<text text-anchor="start" x="185" y="-364" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 <!-- _p_ortho0 -->
 <!-- _p_ortho0_initial -->
 <g id="node10" class="node">
 <title>_p_ortho0_initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="85" cy="-531.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="75" cy="-531.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _p_ortho0_a -->
 <g id="node14" class="node">
 <title>_p_ortho0_a</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="113,-444 57,-444 57,-408 113,-408 113,-444"/>
-<text text-anchor="start" x="81.6646" y="-422.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">a</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M69.3333,-409C69.3333,-409 100.6667,-409 100.6667,-409 106.3333,-409 112,-414.6667 112,-420.3333 112,-420.3333 112,-431.6667 112,-431.6667 112,-437.3333 106.3333,-443 100.6667,-443 100.6667,-443 69.3333,-443 69.3333,-443 63.6667,-443 58,-437.3333 58,-431.6667 58,-431.6667 58,-420.3333 58,-420.3333 58,-414.6667 63.6667,-409 69.3333,-409"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="103,-444 47,-444 47,-408 103,-408 103,-444"/>
+<text text-anchor="start" x="71.6646" y="-422.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">a</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M59.3333,-409C59.3333,-409 90.6667,-409 90.6667,-409 96.3333,-409 102,-414.6667 102,-420.3333 102,-420.3333 102,-431.6667 102,-431.6667 102,-437.3333 96.3333,-443 90.6667,-443 90.6667,-443 59.3333,-443 59.3333,-443 53.6667,-443 48,-437.3333 48,-431.6667 48,-431.6667 48,-420.3333 48,-420.3333 48,-414.6667 53.6667,-409 59.3333,-409"/>
 </g>
 <!-- _p_ortho0_initial&#45;&gt;_p_ortho0_a -->
 <g id="edge6" class="edge">
 <title>_p_ortho0_initial&#45;&gt;_p_ortho0_a</title>
-<path fill="none" stroke="#000000" d="M85,-525.8288C85,-521.1736 85,-514.4097 85,-508.5 85,-508.5 85,-508.5 85,-461.5 85,-459.1079 85,-456.6252 85,-454.1342"/>
-<polygon fill="#000000" stroke="#000000" points="88.5001,-454.0597 85,-444.0598 81.5001,-454.0598 88.5001,-454.0597"/>
-<text text-anchor="middle" x="86.3895" y="-482" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M75,-525.8288C75,-521.1736 75,-514.4097 75,-508.5 75,-508.5 75,-508.5 75,-461.5 75,-459.1079 75,-456.6252 75,-454.1342"/>
+<polygon fill="#000000" stroke="#000000" points="78.5001,-454.0597 75,-444.0598 71.5001,-454.0598 78.5001,-454.0597"/>
+<text text-anchor="middle" x="76.3895" y="-482" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _p_ortho0_d -->
 <g id="node11" class="node">
 <title>_p_ortho0_d</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="138,-70 32,-70 32,-24 138,-24 138,-70"/>
-<text text-anchor="start" x="74.995" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">d ✓</text>
-<text text-anchor="start" x="37.5022" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.in_d</text>
-<polygon fill="#000000" stroke="#000000" points="32,-47 32,-47 138,-47 138,-47 32,-47"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M45,-25C45,-25 125,-25 125,-25 131,-25 137,-31 137,-37 137,-37 137,-57 137,-57 137,-63 131,-69 125,-69 125,-69 45,-69 45,-69 39,-69 33,-63 33,-57 33,-57 33,-37 33,-37 33,-31 39,-25 45,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="118,-70 32,-70 32,-24 118,-24 118,-70"/>
+<text text-anchor="start" x="64.995" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">d ✓</text>
+<text text-anchor="start" x="37.5078" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^in_d</text>
+<polygon fill="#000000" stroke="#000000" points="32,-47 32,-47 118,-47 118,-47 32,-47"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M45,-25C45,-25 105,-25 105,-25 111,-25 117,-31 117,-37 117,-37 117,-57 117,-57 117,-63 111,-69 105,-69 105,-69 45,-69 45,-69 39,-69 33,-63 33,-57 33,-57 33,-37 33,-37 33,-31 39,-25 45,-25"/>
 </g>
 <!-- _p_ortho0_c -->
 <g id="node12" class="node">
 <title>_p_ortho0_c</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="138,-198 32,-198 32,-152 138,-152 138,-198"/>
-<text text-anchor="start" x="82" y="-181.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">c</text>
-<text text-anchor="start" x="37.8376" y="-161.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.in_c</text>
-<polygon fill="#000000" stroke="#000000" points="32,-175 32,-175 138,-175 138,-175 32,-175"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M45,-153C45,-153 125,-153 125,-153 131,-153 137,-159 137,-165 137,-165 137,-185 137,-185 137,-191 131,-197 125,-197 125,-197 45,-197 45,-197 39,-197 33,-191 33,-185 33,-185 33,-165 33,-165 33,-159 39,-153 45,-153"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="118,-198 32,-198 32,-152 118,-152 118,-198"/>
+<text text-anchor="start" x="72" y="-181.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">c</text>
+<text text-anchor="start" x="37.8432" y="-161.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^in_c</text>
+<polygon fill="#000000" stroke="#000000" points="32,-175 32,-175 118,-175 118,-175 32,-175"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M45,-153C45,-153 105,-153 105,-153 111,-153 117,-159 117,-165 117,-165 117,-185 117,-185 117,-191 111,-197 105,-197 105,-197 45,-197 45,-197 39,-197 33,-191 33,-185 33,-185 33,-165 33,-165 33,-159 39,-153 45,-153"/>
 </g>
 <!-- _p_ortho0_c&#45;&gt;_p_ortho0_d -->
 <g id="edge7" class="edge">
 <title>_p_ortho0_c&#45;&gt;_p_ortho0_d</title>
-<path fill="none" stroke="#000000" d="M85,-151.8694C85,-146.1895 85,-140.125 85,-134.5 85,-134.5 85,-134.5 85,-87.5 85,-85.127 85,-82.6757 85,-80.2081"/>
-<polygon fill="#000000" stroke="#000000" points="88.5001,-80.1306 85,-70.1306 81.5001,-80.1306 88.5001,-80.1306"/>
-<text text-anchor="start" x="85" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M75,-151.8694C75,-146.1895 75,-140.125 75,-134.5 75,-134.5 75,-134.5 75,-87.5 75,-85.127 75,-82.6757 75,-80.2081"/>
+<polygon fill="#000000" stroke="#000000" points="78.5001,-80.1306 75,-70.1306 71.5001,-80.1306 78.5001,-80.1306"/>
+<text text-anchor="start" x="75" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 <!-- _p_ortho0_b -->
 <g id="node13" class="node">
 <title>_p_ortho0_b</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="138,-326 32,-326 32,-280 138,-280 138,-326"/>
-<text text-anchor="start" x="74.995" y="-309.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">b ✓</text>
-<text text-anchor="start" x="37.5022" y="-289.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.in_b</text>
-<polygon fill="#000000" stroke="#000000" points="32,-303 32,-303 138,-303 138,-303 32,-303"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M45,-281C45,-281 125,-281 125,-281 131,-281 137,-287 137,-293 137,-293 137,-313 137,-313 137,-319 131,-325 125,-325 125,-325 45,-325 45,-325 39,-325 33,-319 33,-313 33,-313 33,-293 33,-293 33,-287 39,-281 45,-281"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="118,-326 32,-326 32,-280 118,-280 118,-326"/>
+<text text-anchor="start" x="64.995" y="-309.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">b ✓</text>
+<text text-anchor="start" x="37.5078" y="-289.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^in_b</text>
+<polygon fill="#000000" stroke="#000000" points="32,-303 32,-303 118,-303 118,-303 32,-303"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M45,-281C45,-281 105,-281 105,-281 111,-281 117,-287 117,-293 117,-293 117,-313 117,-313 117,-319 111,-325 105,-325 105,-325 45,-325 45,-325 39,-325 33,-319 33,-313 33,-313 33,-293 33,-293 33,-287 39,-281 45,-281"/>
 </g>
 <!-- _p_ortho0_b&#45;&gt;_p_ortho0_c -->
 <g id="edge8" class="edge">
 <title>_p_ortho0_b&#45;&gt;_p_ortho0_c</title>
-<path fill="none" stroke="#000000" d="M85,-279.8694C85,-274.1895 85,-268.125 85,-262.5 85,-262.5 85,-262.5 85,-215.5 85,-213.127 85,-210.6757 85,-208.2081"/>
-<polygon fill="#000000" stroke="#000000" points="88.5001,-208.1306 85,-198.1306 81.5001,-208.1306 88.5001,-208.1306"/>
-<text text-anchor="start" x="85" y="-236" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M75,-279.8694C75,-274.1895 75,-268.125 75,-262.5 75,-262.5 75,-262.5 75,-215.5 75,-213.127 75,-210.6757 75,-208.2081"/>
+<polygon fill="#000000" stroke="#000000" points="78.5001,-208.1306 75,-198.1306 71.5001,-208.1306 78.5001,-208.1306"/>
+<text text-anchor="start" x="75" y="-236" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 <!-- _p_ortho0_a&#45;&gt;_p_ortho0_b -->
 <g id="edge9" class="edge">
 <title>_p_ortho0_a&#45;&gt;_p_ortho0_b</title>
-<path fill="none" stroke="#000000" d="M85,-407.9402C85,-402.3497 85,-396.1701 85,-390.5 85,-390.5 85,-390.5 85,-343.5 85,-341.127 85,-338.6757 85,-336.2081"/>
-<polygon fill="#000000" stroke="#000000" points="88.5001,-336.1306 85,-326.1306 81.5001,-336.1306 88.5001,-336.1306"/>
-<text text-anchor="start" x="85" y="-364" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M75,-407.9402C75,-402.3497 75,-396.1701 75,-390.5 75,-390.5 75,-390.5 75,-343.5 75,-341.127 75,-338.6757 75,-336.2081"/>
+<polygon fill="#000000" stroke="#000000" points="78.5001,-336.1306 75,-326.1306 71.5001,-336.1306 78.5001,-336.1306"/>
+<text text-anchor="start" x="75" y="-364" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 62 - 51
test/test_files/semantics/big_step_maximality/test_ortho_syntactic.xml

@@ -4,63 +4,74 @@
     <semantics
       big_step_maximality="syntactic"
       input_event_lifeline="whole"/>
-    <datamodel/>
-    <tree>
-      <state>
-        <parallel id="p">
-          <state id="ortho0" initial="a">
-            <state id="a">
-              <transition port="in" event="e" target="../b"/>
-            </state>
-            <state id="b" stable="true">
-              <onentry>
-                <raise event="in_b" port="out"/>
-              </onentry>
-              <transition port="in" event="e" target="../c"/>
-            </state>
-            <state id="c">
-              <onentry>
-                <raise event="in_c" port="out"/>
-              </onentry>
-              <transition port="in" event="e" target="../d"/>
-            </state>
-            <state id="d" stable="true">
-              <onentry>
-                <raise event="in_d" port="out"/>
-              </onentry>
-            </state>
+
+    <inport name="in">
+      <event name="e"/>
+    </inport>
+
+    <outport name="out">
+      <event name="in_b"/>
+      <event name="in_c"/>
+      <event name="in_d"/>
+      <event name="in_f"/>
+      <event name="in_g"/>
+      <event name="in_h"/>
+    </outport>
+
+    <root>
+      <parallel id="p">
+        <state id="ortho0" initial="a">
+          <state id="a">
+            <transition event="e" target="../b"/>
+          </state>
+          <state id="b" stable="true">
+            <onentry>
+              <raise event="in_b"/>
+            </onentry>
+            <transition event="e" target="../c"/>
+          </state>
+          <state id="c">
+            <onentry>
+              <raise event="in_c"/>
+            </onentry>
+            <transition event="e" target="../d"/>
           </state>
+          <state id="d" stable="true">
+            <onentry>
+              <raise event="in_d"/>
+            </onentry>
+          </state>
+        </state>
 
-          <state id="ortho1" initial="e">
-            <state id="e">
-              <transition port="in" event="e" target="../f"/>
-            </state>
-            <state id="f">
-              <onentry>
-                <raise event="in_f" port="out"/>
-              </onentry>
-              <transition port="in" event="e" target="../g"/>
-            </state>
-            <state id="g" stable="true">
-              <onentry>
-                <raise event="in_g" port="out"/>
-              </onentry>
-              <transition port="in" event="e" target="../h"/>
-            </state>
-            <state id="h" stable="true">
-              <onentry>
-                <raise event="in_h" port="out"/>
-              </onentry>
-            </state>
+        <state id="ortho1" initial="e">
+          <state id="e">
+            <transition event="e" target="../f"/>
+          </state>
+          <state id="f">
+            <onentry>
+              <raise event="in_f"/>
+            </onentry>
+            <transition event="e" target="../g"/>
+          </state>
+          <state id="g" stable="true">
+            <onentry>
+              <raise event="in_g"/>
+            </onentry>
+            <transition event="e" target="../h"/>
+          </state>
+          <state id="h" stable="true">
+            <onentry>
+              <raise event="in_h"/>
+            </onentry>
           </state>
-        </parallel>
-      </state>
-    </tree>
+        </state>
+      </parallel>
+    </root>
   </statechart>
 
   <input>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
   </input>
 
   <output>

+ 1 - 1
test/test_files/semantics/big_step_maximality/test_ortho_takemany.xml

@@ -5,7 +5,7 @@
       big_step_maximality="take_many"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/big_step_maximality/test_ortho_takeone.xml

@@ -5,7 +5,7 @@
       big_step_maximality="take_one"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/statechart_flat.svg

@@ -58,7 +58,7 @@
 <title>_a&#45;&gt;_b</title>
 <path fill="none" stroke="#000000" d="M53,-147.8711C53,-142.4482 53,-136.3229 53,-130.2494"/>
 <polygon fill="#000000" stroke="#000000" points="56.5001,-130.21 53,-120.21 49.5001,-130.21 56.5001,-130.21"/>
-<text text-anchor="start" x="53" y="-131" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e^f &#160;&#160;</text>
+<text text-anchor="start" x="53" y="-131" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e^f &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 17 - 19
test/test_files/semantics/event_lifeline/statechart_flat.xml

@@ -2,24 +2,22 @@
 <statechart>
   <semantics/>
   <datamodel/>
-  <tree>
-    <state initial="a">
-      <state id="a">
-        <transition event="e" port="in" target="/b">
-          <raise event="f"/>
-        </transition>
-      </state>
-      <state id="b">
-        <onentry>
-          <raise event="in_b" port="out"/>
-        </onentry>
-        <transition event="f" target="/c"/>
-      </state>
-      <state id="c">
-        <onentry>
-          <raise event="in_c" port="out"/>
-        </onentry>
-      </state>
+  <root initial="a">
+    <state id="a">
+      <transition event="e" port="in" target="/b">
+        <raise event="f"/>
+      </transition>
     </state>
-  </tree>
+    <state id="b">
+      <onentry>
+        <raise event="in_b" port="out"/>
+      </onentry>
+      <transition event="f" target="/c"/>
+    </state>
+    <state id="c">
+      <onentry>
+        <raise event="in_c" port="out"/>
+      </onentry>
+    </state>
+  </root>
 </statechart>

+ 1 - 1
test/test_files/semantics/event_lifeline/statechart_ortho.svg

@@ -123,7 +123,7 @@
 <title>_p_o0_a&#45;&gt;_p_o0_b</title>
 <path fill="none" stroke="#000000" d="M85,-287.9402C85,-282.3497 85,-276.1701 85,-270.5 85,-270.5 85,-270.5 85,-223.5 85,-221.127 85,-218.6757 85,-216.2081"/>
 <polygon fill="#000000" stroke="#000000" points="88.5001,-216.1306 85,-206.1306 81.5001,-216.1306 88.5001,-216.1306"/>
-<text text-anchor="start" x="85" y="-244" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e^f &#160;&#160;</text>
+<text text-anchor="start" x="85" y="-244" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e^f &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 30 - 32
test/test_files/semantics/event_lifeline/statechart_ortho.xml

@@ -1,37 +1,35 @@
 <?xml version="1.0" ?>
 <statechart>
-  <tree>
-    <state>
-      <parallel id="p">
-        <state id="o0" initial="a">
-          <state id="a">
-            <transition event="e" port="in" target="../b">
-              <raise event="f"/>
-            </transition>
-          </state>
-          <state id="b">
-            <onentry>
-              <raise event="in_b" port="out"/>
-            </onentry>
-            <transition event="f" target="../c"/>
-          </state>
-          <state id="c">
-            <onentry>
-              <raise event="in_c" port="out"/>
-            </onentry>
-          </state>
+  <root>
+    <parallel id="p">
+      <state id="o0" initial="a">
+        <state id="a">
+          <transition event="e" port="in" target="../b">
+            <raise event="f"/>
+          </transition>
         </state>
-        <state id="o1" initial="d">
-          <state id="d">
-            <transition event="f" target="../e"/>
-          </state>
-          <state id="e">
-            <onentry>
-              <raise event="in_e" port="out"/>
-            </onentry>
-          </state>
+        <state id="b">
+          <onentry>
+            <raise event="in_b" port="out"/>
+          </onentry>
+          <transition event="f" target="../c"/>
         </state>
-      </parallel>
-    </state>
-  </tree>
+        <state id="c">
+          <onentry>
+            <raise event="in_c" port="out"/>
+          </onentry>
+        </state>
+      </state>
+      <state id="o1" initial="d">
+        <state id="d">
+          <transition event="f" target="../e"/>
+        </state>
+        <state id="e">
+          <onentry>
+            <raise event="in_e" port="out"/>
+          </onentry>
+        </state>
+      </state>
+    </parallel>
+  </root>
 </statechart>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_flat_nextbs.xml

@@ -7,7 +7,7 @@
       input_event_lifeline="*"/>
   </statechart>
   <input>
-      <input_event name="e" port="in" time="0 d"/>
+      <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_flat_nextss_takemany.xml

@@ -7,7 +7,7 @@
       input_event_lifeline="*"/>
   </statechart>
   <input>
-      <input_event name="e" port="in" time="0 d"/>
+      <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_flat_nextss_takeone.xml

@@ -7,7 +7,7 @@
       input_event_lifeline="*"/>
   </statechart>
   <input>
-      <input_event name="e" port="in" time="0 d"/>
+      <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_ortho_nextbs.xml

@@ -7,7 +7,7 @@
       input_event_lifeline="whole"/>
   </statechart>
   <input>
-      <input_event name="e" port="in" time="0 d"/>
+      <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_ortho_nextcs_takemany.xml

@@ -8,7 +8,7 @@
       input_event_lifeline="*"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_ortho_nextcs_takeone.xml

@@ -7,7 +7,7 @@
       input_event_lifeline="*"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 1 - 1
test/test_files/semantics/event_lifeline/test_ortho_nextss.xml

@@ -7,7 +7,7 @@
       input_event_lifeline="*"/>
   </statechart>
   <input>
-    <input_event name="e" port="in" time="0 d"/>
+    <event name="e" port="in" time="0 d"/>
   </input>
   <output>
     <big_step>

+ 17 - 19
test/test_files/semantics/memory_protocol/fail_race_condition.xml

@@ -8,30 +8,28 @@
     <datamodel>
       <var id="x" expr="0"/>
     </datamodel>
-    <tree>
-      <state>
-        <parallel id="p">
-          <state id="a">
-            <state id="a1">
-              <transition port="in" event="e" target=".">
-                <code> x += 1; </code>
-              </transition>
-            </state>
+    <root>
+      <parallel id="p">
+        <state id="a">
+          <state id="a1">
+            <transition port="in" event="e" target=".">
+              <code> x += 1; </code>
+            </transition>
           </state>
+        </state>
 
-          <state id="b">
-            <state id="a1">
-              <transition port="in" event="e" target=".">
-                <code> x += 1; </code>
-              </transition>
-            </state>
+        <state id="b">
+          <state id="a1">
+            <transition port="in" event="e" target=".">
+              <code> x += 1; </code>
+            </transition>
           </state>
-        </parallel>
-      </state>
-    </tree>
+        </state>
+      </parallel>
+    </root>
   </statechart>
   <input>
-    <input_event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
   </input>
   <output>
 

+ 25 - 25
test/test_files/semantics/memory_protocol/statechart_enabledness.svg

@@ -4,25 +4,25 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="510pt" height="412pt"
- viewBox="0.00 0.00 510.00 412.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="499pt" height="412pt"
+ viewBox="0.00 0.00 499.00 412.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 408)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-408 506,-408 506,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-408 495,-408 495,4 -4,4"/>
 <g id="clust1" class="cluster">
 <title>cluster__p</title>
-<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 482,-8 482,-8 488,-8 494,-14 494,-20 494,-20 494,-353 494,-353 494,-359 488,-365 482,-365 482,-365 20,-365 20,-365 14,-365 8,-359 8,-353 8,-353 8,-20 8,-20 8,-14 14,-8 20,-8"/>
-<text text-anchor="start" x="247.6646" y="-346.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">p</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 471,-8 471,-8 477,-8 483,-14 483,-20 483,-20 483,-353 483,-353 483,-359 477,-365 471,-365 471,-365 20,-365 20,-365 14,-365 8,-359 8,-353 8,-353 8,-20 8,-20 8,-14 14,-8 20,-8"/>
+<text text-anchor="start" x="242.1646" y="-346.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">p</text>
 </g>
 <g id="clust2" class="cluster">
 <title>cluster__p_status</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="360,-16 360,-327 486,-327 486,-16 360,-16"/>
-<text text-anchor="start" x="406.9944" y="-308.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">status</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="349,-16 349,-327 475,-327 475,-16 349,-16"/>
+<text text-anchor="start" x="395.9944" y="-308.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">status</text>
 </g>
 <g id="clust3" class="cluster">
 <title>cluster__p_increment</title>
-<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-152 24,-327 352,-327 352,-152 24,-152"/>
-<text text-anchor="start" x="161.6648" y="-308.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">increment</text>
+<polygon fill="none" stroke="#000000" stroke-dasharray="5,2" points="24,-152 24,-327 341,-327 341,-152 24,-152"/>
+<text text-anchor="start" x="156.1648" y="-308.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">increment</text>
 </g>
 <!-- __initial -->
 <g id="node1" class="node">
@@ -41,37 +41,37 @@
 <!-- _p_status_initial -->
 <g id="node4" class="node">
 <title>_p_status_initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="423" cy="-283.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="412" cy="-283.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _p_status_counting -->
 <g id="node6" class="node">
 <title>_p_status_counting</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="456.5,-196 389.5,-196 389.5,-160 456.5,-160 456.5,-196"/>
-<text text-anchor="start" x="400.8242" y="-174.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">counting</text>
-<path fill="none" stroke="#000000" stroke-width="2" d="M401.8333,-161C401.8333,-161 444.1667,-161 444.1667,-161 449.8333,-161 455.5,-166.6667 455.5,-172.3333 455.5,-172.3333 455.5,-183.6667 455.5,-183.6667 455.5,-189.3333 449.8333,-195 444.1667,-195 444.1667,-195 401.8333,-195 401.8333,-195 396.1667,-195 390.5,-189.3333 390.5,-183.6667 390.5,-183.6667 390.5,-172.3333 390.5,-172.3333 390.5,-166.6667 396.1667,-161 401.8333,-161"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="445.5,-196 378.5,-196 378.5,-160 445.5,-160 445.5,-196"/>
+<text text-anchor="start" x="389.8242" y="-174.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">counting</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M390.8333,-161C390.8333,-161 433.1667,-161 433.1667,-161 438.8333,-161 444.5,-166.6667 444.5,-172.3333 444.5,-172.3333 444.5,-183.6667 444.5,-183.6667 444.5,-189.3333 438.8333,-195 433.1667,-195 433.1667,-195 390.8333,-195 390.8333,-195 385.1667,-195 379.5,-189.3333 379.5,-183.6667 379.5,-183.6667 379.5,-172.3333 379.5,-172.3333 379.5,-166.6667 385.1667,-161 390.8333,-161"/>
 </g>
 <!-- _p_status_initial&#45;&gt;_p_status_counting -->
 <g id="edge2" class="edge">
 <title>_p_status_initial&#45;&gt;_p_status_counting</title>
-<path fill="none" stroke="#000000" d="M423,-277.8288C423,-273.1736 423,-266.4097 423,-260.5 423,-260.5 423,-260.5 423,-213.5 423,-211.1079 423,-208.6252 423,-206.1342"/>
-<polygon fill="#000000" stroke="#000000" points="426.5001,-206.0597 423,-196.0598 419.5001,-206.0598 426.5001,-206.0597"/>
-<text text-anchor="middle" x="424.3895" y="-234" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M412,-277.8288C412,-273.1736 412,-266.4097 412,-260.5 412,-260.5 412,-260.5 412,-213.5 412,-211.1079 412,-208.6252 412,-206.1342"/>
+<polygon fill="#000000" stroke="#000000" points="415.5001,-206.0597 412,-196.0598 408.5001,-206.0598 415.5001,-206.0597"/>
+<text text-anchor="middle" x="413.3895" y="-234" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _p_status_done -->
 <g id="node5" class="node">
 <title>_p_status_done</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="478.5,-70 367.5,-70 367.5,-24 478.5,-24 478.5,-70"/>
-<text text-anchor="start" x="410.1584" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">done</text>
-<text text-anchor="start" x="373.9982" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.done</text>
-<polygon fill="#000000" stroke="#000000" points="368,-47 368,-47 479,-47 479,-47 368,-47"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M380.5,-25C380.5,-25 465.5,-25 465.5,-25 471.5,-25 477.5,-31 477.5,-37 477.5,-37 477.5,-57 477.5,-57 477.5,-63 471.5,-69 465.5,-69 465.5,-69 380.5,-69 380.5,-69 374.5,-69 368.5,-63 368.5,-57 368.5,-57 368.5,-37 368.5,-37 368.5,-31 374.5,-25 380.5,-25"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="467.5,-70 356.5,-70 356.5,-24 467.5,-24 467.5,-70"/>
+<text text-anchor="start" x="399.1584" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">done</text>
+<text text-anchor="start" x="362.9982" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.done</text>
+<polygon fill="#000000" stroke="#000000" points="357,-47 357,-47 468,-47 468,-47 357,-47"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M369.5,-25C369.5,-25 454.5,-25 454.5,-25 460.5,-25 466.5,-31 466.5,-37 466.5,-37 466.5,-57 466.5,-57 466.5,-63 460.5,-69 454.5,-69 454.5,-69 369.5,-69 369.5,-69 363.5,-69 357.5,-63 357.5,-57 357.5,-57 357.5,-37 357.5,-37 357.5,-31 363.5,-25 369.5,-25"/>
 </g>
 <!-- _p_status_counting&#45;&gt;_p_status_done -->
 <g id="edge3" class="edge">
 <title>_p_status_counting&#45;&gt;_p_status_done</title>
-<path fill="none" stroke="#000000" d="M423,-159.7983C423,-152.007 423,-142.8073 423,-134.5 423,-134.5 423,-134.5 423,-87.5 423,-85.127 423,-82.6757 423,-80.2081"/>
-<polygon fill="#000000" stroke="#000000" points="426.5001,-80.1306 423,-70.1306 419.5001,-80.1306 426.5001,-80.1306"/>
-<text text-anchor="start" x="423" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[i == 2] &#160;&#160;</text>
+<path fill="none" stroke="#000000" d="M412,-159.7983C412,-152.007 412,-142.8073 412,-134.5 412,-134.5 412,-134.5 412,-87.5 412,-85.127 412,-82.6757 412,-80.2081"/>
+<polygon fill="#000000" stroke="#000000" points="415.5001,-80.1306 412,-70.1306 408.5001,-80.1306 415.5001,-80.1306"/>
+<text text-anchor="start" x="412" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">[i == 2] &#160;&#160;</text>
 </g>
 <!-- _p_increment -->
 <!-- _p_increment_initial -->
@@ -98,7 +98,7 @@
 <title>_p_increment_a&#45;&gt;_p_increment_a</title>
 <path fill="none" stroke="#000000" d="M88.0183,-182.8247C99.888,-183.1883 110,-181.5801 110,-178 110,-175.5387 105.2205,-174.0094 98.3762,-173.4121"/>
 <polygon fill="#000000" stroke="#000000" points="98.0957,-169.9049 88.0183,-173.1753 97.9356,-176.903 98.0957,-169.9049"/>
-<text text-anchor="start" x="110" y="-175" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">in.e [not INSTATE([&quot;/p/status/done&quot;])]^out.inc /i += 1 &#160;&#160;</text>
+<text text-anchor="start" x="110" y="-175" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">e [not INSTATE([&quot;/p/status/done&quot;])]^out.inc /i += 1 &#160;&#160;</text>
 </g>
 </g>
 </svg>

+ 20 - 22
test/test_files/semantics/memory_protocol/statechart_enabledness.xml

@@ -3,29 +3,27 @@
   <datamodel>
     <var id="i" expr="0"/>
   </datamodel>
-  <tree>
-    <state>
-      <parallel id="p">
-        <state id="increment">
-          <state id="a">
-            <transition port="in" event="e" target="." cond='not INSTATE(["/p/status/done"])'>
-              <raise port="out" event="inc"/>
-              <code> i += 1; </code>
-            </transition>
-          </state>
+  <root>
+    <parallel id="p">
+      <state id="increment">
+        <state id="a">
+          <transition port="in" event="e" target="." cond='not INSTATE(["/p/status/done"])'>
+            <raise port="out" event="inc"/>
+            <code> i += 1; </code>
+          </transition>
         </state>
+      </state>
 
-        <state id="status" initial="counting">
-          <state id="counting">
-            <transition cond="i == 2" target="../done"/>
-          </state>
-          <state id="done">
-            <onentry>
-              <raise port="out" event="done"/>
-            </onentry>
-          </state>
+      <state id="status" initial="counting">
+        <state id="counting">
+          <transition cond="i == 2" target="../done"/>
         </state>
-      </parallel>
-    </state>
-  </tree>
+        <state id="done">
+          <onentry>
+            <raise port="out" event="done"/>
+          </onentry>
+        </state>
+      </state>
+    </parallel>
+  </root>
 </statechart>

+ 6 - 6
test/test_files/semantics/memory_protocol/test_gcbig.xml

@@ -8,12 +8,12 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
-    <input_event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
   </input>
 
   <output>

+ 1 - 1
test/test_files/semantics/memory_protocol/test_gccombo.xml

@@ -9,7 +9,7 @@
   </statechart>
 
   <input>
-    <input_event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
   </input>
 
   <output>

+ 1 - 1
test/test_files/semantics/memory_protocol/test_gcsmall.xml

@@ -9,7 +9,7 @@
   </statechart>
   
   <input>
-    <input_event port="in" name="e" time="0 d"/>
+    <event port="in" name="e" time="0 d"/>
   </input>
 
   <output>

+ 4 - 6
test/test_files/syntax/fail_after_and_event.xml

@@ -4,13 +4,11 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
-      <state>
-        <state id="a">
-          <transition after="1 s" event="e" target="."/>
-        </state>
+    <root>
+      <state id="a">
+        <transition after="1 s" event="e" target="."/>
       </state>
-    </tree>
+    </root>
   </statechart>
 
   <output>

+ 3 - 5
test/test_files/syntax/fail_no_id.xml

@@ -4,12 +4,10 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
-      <state>
-        <state><!-- non-root state must have 'id' -->
-        </state>
+    <root>
+      <state><!-- non-root state must have 'id' -->
       </state>
-    </tree>
+    </root>
   </statechart>
 
   <output>

+ 4 - 6
test/test_files/syntax/fail_missing_initial.xml

@@ -4,13 +4,11 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
+    <root>
       <!-- missing initial -->
-      <state>
-        <state id="a"/>
-        <state id="b"/>
-      </state>
-    </tree>
+      <state id="a"/>
+      <state id="b"/>
+    </root>
   </statechart>
 
   <output>

+ 2 - 2
test/test_files/syntax/fail_missing_root.xml

@@ -4,9 +4,9 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
+    <state>
       <!-- not allowed: no root state -->
-    </tree>
+    </state>
   </statechart>
 
   <output>

+ 4 - 6
test/test_files/syntax/fail_missing_target.xml

@@ -4,13 +4,11 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
-      <state>
-        <state id="a">
-          <transition event="e"/>
-        </state>
+    <root>
+      <state id="a">
+        <transition event="e"/>
       </state>
-    </tree>
+    </root>
   </statechart>
 
   <output>

+ 7 - 5
test/test_files/syntax/fail_multiple_root.xml

@@ -4,11 +4,13 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
-      <!-- not allowed: more than one root state -->
-      <state/>
-      <state/>
-    </tree>
+    <root>
+      <state id="a"/>
+    </root>
+    <!-- not allowed: more than one root state -->
+    <root>
+      <state id="b"/>
+    </root>
   </statechart>
 
   <output>

+ 4 - 6
test/test_files/syntax/fail_root_transition.xml

@@ -4,12 +4,10 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
-      <state>
-        <!-- not allowed: transition with source: root -->
-        <transition target="."/>
-      </state>
-    </tree>
+    <root>
+      <!-- not allowed: transition with source: root -->
+      <transition target="."/>
+    </root>
   </statechart>
 
   <output>

+ 4 - 6
test/test_files/syntax/fail_sibling_id.xml

@@ -4,12 +4,10 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
-      <state initial="a">
-        <state id="a"/>
-        <state id="a"/>
-      </state>
-    </tree>
+    <root initial="a">
+      <state id="a"/>
+      <state id="a"/>
+    </root>
   </statechart>
 
   <output>

+ 4 - 6
test/test_files/syntax/fail_wrong_initial.xml

@@ -4,13 +4,11 @@
     <semantics/>
     <datamodel/>
 
-    <tree>
+    <root initial="c">
       <!-- initial doesn't exist -->
-      <state initial="c">
-        <state id="a"/>
-        <state id="b"/>
-      </state>
-    </tree>
+      <state id="a"/>
+      <state id="b"/>
+    </root>
   </statechart>
 
   <output>