Browse Source

MPIDE-27: remove expressions from interactions

Pre- and post-conditions (that is, expressions in interactions) are now
defined within code blocks surrounding the appropriate selectors,
instead of being treated as operands for the interaction. Interactions
themselves were refactored to no longer need an check for mismatched
types.

Removed redundant expression code.
Austin Meagher 10 years ago
parent
commit
b75b620b80
2 changed files with 65 additions and 83 deletions
  1. 38 39
      docs/modellang.bnf
  2. 27 44
      src/lib/parser/modellang.pegjs

+ 38 - 39
docs/modellang.bnf

@@ -1,77 +1,76 @@
 <model>  ::=
     <statement> ";" <model>
-    |  <statement>
+    | <statement>
 
 <statement> ::=
     <system>
-    |  <behavior>
-    |  <interaction>
-    |  <trigger>
+    | <behavior>
+    | <interaction>
+    | <trigger>
 
 <system> ::= "SYSTEM" <systemId> "=" <definitionPattern>
 <behavior> ::= "BEHAVIOR" <behaviorId> "=" <definitionPattern>
 <interaction> ::= "INTERACTION" <interactionBody>
-<trigger> ::= "WHEN" <selectionPattern> <triggerBody>
+<trigger> ::= "WHEN" <selectionPatternSans> <codeBlock>
 
 <definitionPattern> ::=
     <alternation>
-    |  <sequence>
+    | <sequence>
 
 <alternation> ::=
     <element> "|" <alternation>
-    |  <element> "|" <element>
+    | <element> "|" <element>
 
 <sequence> ::=
     <element> <sequence>
-    |  <element>
+    | <element>
 
 <element> ::=
     "(" <definitionPattern> ")" <quantifier>
-    |  <event> <quantifier>
+    | <event> <quantifier>
 
-<event> ::= <identifier>
+<event> ::=
+    <identifier>
 
 <quantifier> ::=
     "*"
-    |  "+"
-    |  "?"
-    |  "{" integer "}"
-    |  "{" integer "," "}"
-    |  "{" integer "," integer "}"
-    |  empty
+    | "+"
+    | "?"
+    | "{" integer "}"
+    | "{" integer "," "}"
+    | "{" integer "," integer "}"
+    | empty
 
 <interactionBody> ::=
-    <interactionOperand> <interactionOperator> <interactionBody>
-    |  <interactionOperand> <interactionOperator> <interactionOperand>
+    <interactionJoin>
+    | <interactionThen>
 
-<interactionOperand> ::=
-    <selectionPattern>
-    |  <expression>
+<interactionJoin> ::=
+    <selectionPatternSans> <join> <interactionJoin>
+    | <selectionPatternSans> <join> <selectionPatternSans>
 
-<interactionOperator> ::=
-    "->"
-    |  "=="
+<interactionThen> ::=
+    <selectionPattern> <then> <interactionThen>
+    | <selectionPattern> <then> <selectionPattern>
 
 <selectionPattern> ::=
-    <systemId> ":" <definitionPattern>
+    <codeBlock> <systemId> ":" <definitionPattern> <codeBlock>
+    | <systemId> ":" <definitionPattern> <codeBlock>
+    | <codeBlock> <systemId> ":" <definitionPattern>
+    | <selectionPatternSans>
 
-<expression> ::=
-    <term> <expressionOperator> <expression>
-    |  <term>
+<selectionPatternSans> ::=
+    <systemId> ":" <definitionPattern>
 
-<expressionOperator> ::=
-    ">"
-    |  "<"
-    |  ">="
-    |  "<="
-    |  "=="
+<join> ::=
+    "=="
 
-<term> ::=
-    integer
-    |  string
-    |  property
+<then> ::=
+    "->"
 
-<triggerBody> ::= "{" triggerClause "}" // TODO: expand on triggerClause implementation
+<codeBlock> ::=
+    "{" text <codeBlock> text "}"
+    | "{" text "}"
 
 <systemId> ::= <identifier>
 <behaviorId> ::= <identifier>

+ 27 - 44
src/lib/parser/modellang.pegjs

@@ -49,7 +49,7 @@
                 case "Behavior":
                     model.behaviors[statement.id] = statement;
                     break;
-                case "Order":
+                case "Then":
                 case "Join":
                     model.interactions.push(statement);
                     break;
@@ -173,17 +173,12 @@
             this.body = body;
         },
 
-        Selector: function Selector(system, pattern) {
+        Selector: function Selector(system, pattern, pre, post) {
             ast.Base.call(this, "Selector");
             this.system = system;
             this.pattern = pattern;
-        },
-
-        Expression: function Expression(op, lhs, rhs) {
-            ast.Base.call(this, "Expression");
-            this.operator = op;
-            this.lhs = lhs;
-            this.rhs = rhs;
+            this.pre = pre;
+            this.post = post;
         },
 
         Trigger: function Trigger(selector, body) {
@@ -223,41 +218,32 @@ behavior_statement "Behavior"
     { return new ast.Behavior(id, body, ast.localrefs); }
 
 interaction_statement "Interaction"
-    = _INTERACTION_ _COLON_ first:( system_item_selector / expression )
-    type:interaction_type second:( system_item_selector / expression )
-    !{ ast.interactionType = type; }
-    tail:(
-        type2:interaction_type
-        !{ if (type2 !== ast.interactionType) ast.errors.push(err("ERROR: Mixed interaction types", null, { expected:ast.interactionType, found:type2 })); }
-        tail2:( system_item_selector / expression )
-        { return tail2; }
-    )*
-    { return new ast.Interaction(type, [first, second].concat(tail)); }
+    = _INTERACTION_ _COLON_ interaction:interaction_body
+    { return interaction; }
+
+interaction_body
+    = first:system_item_selector _ type:THEN _
+    second:system_item_selector rest:(_ THEN _ a:system_item_selector { return a; })*
+    { return new ast.Interaction(type, [first, second].concat(rest)); }
+    / first:system_item_selector_sans _ type:JOIN _
+    second:system_item_selector_sans rest:(_ JOIN _ a:system_item_selector_sans { return a; })*
+    { return new ast.Interaction(type, [first, second].concat(rest)); }
 
 interaction_type
-    = _ t:( ORDER / JOIN ) _
+    = _ t:( THEN / JOIN ) _
     { return t; }
 
 system_item_selector "Selector"
-    = !([a-z0-9 ]i+ operator) !{ ast.selector = true; } _ sys:system_id ":" _ p:behavior_pattern _
-    { ast.selector = false; return new ast.Selector(sys, p); }
-
-expression "Expression"
-    = term:term op:operator expr:expression
-    { return new ast.Expression(op, term, expr); }
-    / term
-
-term
-    = _ i:INT _ { return i; }
-    / _QUOTE s:ID QUOTE_ { return s; }
-    / property /* TODO: properties */
-
-operator
-    = _ o:">" _ { return o; }
-    / _ o:"<" _ { return o; }
-    / _ o:">=" _ { return o; }
-    / _ o:"<=" _ { return o; }
-    / _ o:"==" _ { return o; }
+    = !{ ast.selector = true; }
+    _ pre:("{" c:embedded_code "}" { return c; })? _
+    sys:system_id ":" _ pattern:behavior_pattern
+    _ post:("{" c:embedded_code "}" { return c; })? _
+    { ast.selector = false; return new ast.Selector(sys, pattern, pre, post); }
+
+system_item_selector_sans "Selector"
+    = !{ ast.selector = true; }
+    _ sys:system_id ":" _ pattern:behavior_pattern _
+    { ast.selector = false; return new ast.Selector(sys, pattern); }
 
 behavior_pattern "Behavior Pattern"
     = (alternation / sequence)+
@@ -291,7 +277,7 @@ quantifier_range
     { return minmaxify(lo, hi); }
 
 trigger "Trigger"
-    = _WHEN_ _COLON_ selector:( system_item_selector / expression ) "{" body:embedded_code "}"
+    = _WHEN_ _COLON_ selector:system_item_selector_sans "{" body:embedded_code "}"
     { return new ast.Trigger(selector, body); }
 
 embedded_code
@@ -300,7 +286,6 @@ embedded_code
 
 behavior_id = id:ID { return id; }
 system_id   = id:ID { return id; }
-property    = id:ID { return id; }
 
 event_ref   = id:ID
     {
@@ -321,7 +306,7 @@ BEHAVIOR       = t:"BEHAVIOR"         { return t; }
 INTERACTION    = t:"INTERACTION"      { return t; }
 WHEN           = t:"WHEN"             { return t; }
 ASYNC          = t:"ASYNC"            { return t; }
-ORDER          = "->"                 { return "Order"; }
+THEN           = "->"                 { return "Then"; }
 JOIN           = "=="                 { return "Join"; }
 
 _SYSTEM_       = _ t:SYSTEM _         { return t; }
@@ -334,8 +319,6 @@ _COMMA_        = _ t:"," _            { return t; }
 _PIPE_         = _ t:"|" _            { return t; }
 _COLON_        = _ t:":" _            { return t; }
 _SEMI_         = _ t:";" _            { return t; }
-_QUOTE         = _ t:("'" / '"')      { return t; }
-QUOTE_         = t:("'" / '"') _      { return t; }
 
 ID "Identifier"	/*TODO: UNICODE?*/
     = !KEYWORD [A-Za-z] [a-zA-Z0-9_]*