123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948 |
- -- MP2_parser.rig Automated model generator MP2 -> C++
- -- v 2.0
- -- Mikhail Auguston, 03/05/15
- -- last modified 04/05/15
- --
- -- use: parser schema_name output_file scope
- --
- -- takes the source .mp file and creates the intermediate tree
- --
- --------------------------------------------------------------
- #MP
- -- ******** Globals:
- -- $scope -- scope for the model
- -- $main_schema_name -- from the MP model, used to generate container names
- -- $input_schema_name -- from the parameters, should be the same
- -- $triggering_events: <* event_name: T *>
- -- events triggering WHEN, should not appear
- -- in patterns, but may be shared or coordinated
- --
- -- $atomic_events: <* event_name: T *> -- for generating event list in C++
- -- $already_ordered: <* event_name: T *> -- for #order_composites_by_dependency
- -- $composite_order: (. (* event_name *) .) -- retains the composite definition order
- -- for generating harvest() calls
- -- $this contains root, composite event or schema name
- -- for COORDINATE FROM default, reset in #rule
- -- $source_list: <* variable_name: pattern *> -- variables
- -- defined in nested compositions COORDINATE, ENSURE, NEW
- -- and maintained within schema or BUILD block
- -------------------------------------------
- -- these tables are produced by the 1st pass
- -------------------------------------------
- -- $composites: <* composite_event_name: <. rule_type: composite,
- -- work_name: work_name,
- -- pattern_list: $pattern_list,
- -- build_block: $comp_op_list .>
- -- *> -- composites table
- -- $roots: <* root_name: <. rule_type: ROOT,
- -- work_name: work_name,
- -- pattern_list: $pattern_list,
- -- build_block: $comp_op_list .>
- -- *> -- roots table
- --
- -- $coordinate_ops: <* work_name: <. operation: COORDINATE,
- -- work: work_name,
- -- synchronization: $synchronization,
- -- source_list: $coord,
- -- body: $body .> *>
- -- $share_all_ops: <* work_name: <. operation: SHARE_ALL,
- -- work: work_name,
- -- host_list: $sharing_hosts,
- -- shared_events: $shared_events .> *>
- -------------------------------------------
- -- 2nd pass results
- -------------------------------------------
- -- $new_composites: <* composite_event_name: <. rule_type: composite,
- -- work_name: work_name,
- -- pattern_list: $pattern_list,
- -- build_block: $comp_op_list,
- -- called_composites: <* $composite_name: T *> .>
- -- *> -- updated composites table
- -- $new_root_table: <* root_name: <. rule_type: ROOT,
- -- work_name: work_name,
- -- pattern_list: $pattern_list,
- -- build_block: $comp_op_list,
- -- called_composites: <* $composite_name: T *> .>
- -- *> -- updated roots table
- --
- -- $new_share_all_ops: <* work_name: *>
- -----------------------------------------
- -- $unique_number -- to keep work names unique
- -- $errors_detected -- stop reporting errors if it becomes > 3
- -------------------------------------------------------------
- $Parm:= #PARM(T); -- list of all parameters
- $input_schema_name := #IMPLODE( $Parm[1] );
- $this := $input_schema_name;
- $input_file := #IMPLODE( $input_schema_name '.mp');
- $output_file := #IMPLODE( $Parm[2] ); -- for generation phase
- IF $Parm[3] ->
- $scope := $Parm[3]; -- no need to #IMPLODE(), just take the number
- ELSIF T ->
- $scope := 1; -- default scope
- FI;
- OPEN MSG ' '; --for error messages
- --call C lexer
- $Lex:= #CALL_PAS( 35 $input_file 'L+A-U-P-C+p-m+');
-
- --PRINT $Lex; --<<<<<<<<<<<<<<
- MSG<< 'MPhoenix parser v.2.0 input from' $input_file scope $scope
- Total #LEN($Lex) tokens;
-
- $unique_number:= 0;
- $errors_detected:= 0;
-
- --********** 1st pass, do the parsing, $composites, $roots
-
- $complete:= #main_schema( $Lex);
- --*********** 2nd pass, insert/expand composite events,
- -- create $new_root_table, $new_composites
-
- IF $errors_detected = 0 ->
- $new_composites := #build_rules($composites); -- composites first
- #detect_recursion($new_composites);
- $composite_order:= #order_composites_by_dependency($new_composites);
- $new_root_table := #build_rules($roots);
- $new_share_all_ops:= #prepare_share_all($share_all_ops);
-
- FI;
- IF $errors_detected = 0 ->
- --MSG<< 'Parsing completed. Saving result in' $output_file;MSG<<;
- $result:= $complete ++
- -- the contents of $complete returned by #main_schema
- -- <. schema: $id_schema,
- -- include_list: $include_list,
- -- elt_list: $elt_list -- roots, composition ops
- -- .>
-
- <. scope: $scope,
- input_file: $input_file,
- roots: $roots, -- source for comments in C++
- composites: $composites, -- source for comments in C++
- atomic_events: $atomic_events,
- new_root_table: $new_root_table,
- new_composites: $new_composites,
- composite_order: $composite_order,
- coordinate_ops: $coordinate_ops,
- share_all_ops: $new_share_all_ops
- .>;
- SAVE $result $output_file;
- --PRINT $result; --<<<<<<<<<<<<<<<<<<<<
- ELSIF T -> MSG<< 'Errors detected...'
- FI;
-
- ##
- #main_schema
- (. SCHEMA ( $id_schema := #IDENT
- /LAST #MP $main_schema_name := $id_schema/ !
- $x /#error( $x err1 ); FAIL/
- )
-
- /IF (LAST #MP $input_schema_name <> $id_schema) ->
- #error( $id_schema err8 ); FAIL
- FI /
- (* $include_list !.:= #include_clause *)
- (*
- $elt_list !.:=
- ( #rule !
- #composition_operation
- /LAST #MP $source_list:= NULL/ )
- ( ';' ! $x /#error( $x err4 )/ )
- *)
- [ #BUILD_block ]
- .)
- /$filtered_elt_list:= #filter_elt_list($elt_list);
- RETURN <. schema: $id_schema,
- include_list: $include_list,
- elt_list: $filtered_elt_list -- roots, composition ops
- .>/
- ##
- #filter_elt_list
- -- to get rid of plain composite event declarations in schema
- -- leaving only roots and composition ops for schema's class definition
- (. (* ( <. composite: $a .> ! NULL ! $res !.:= $b ) *) .)
- /RETURN $res/
- ##
- --------------------------------------------------------------------
- -----1st pass--- rule syntax ---------------------------------------
- --------------------------------------------------------------------
- #include_clause
- INCLUDE ( $id_schema := #IDENT !
- $x /#error( $x err1 ); FAIL/ )
- ( ';' ! $x /#error( $x err4 ); FAIL/ )
- /RETURN $id_schema/
- ##
- #rule
- -- globals:
- -- $rule_type
- -- $event_name
- /$rule_type:= composite/ -- the default
- [ ROOT /$rule_type:= ROOT/]
- $event_name := #IDENT ':'
- /LAST #MP $this := $event_name; -- switch default for composition FROM
- $defined_event := <. $rule_type: $event_name .>/
- $patterns:= #pattern_list
- [ $build_block := #BUILD_block ]
-
- /$rule_body := <. rule_type: $rule_type,
- work_name: #IMPLODE( 'Comp_'
- #unique_number() '_' LAST #MP $main_schema_name),
- pattern_list: $patterns,
- build_block: $build_block
- .>;
- IF $rule_type = ROOT ->
- LAST #MP $roots ++:= <. $event_name: $rule_body .>;
- ELSIF T -> -- composite event definition
- LAST #MP $composites ++:= <. $event_name: $rule_body .>;
- FI;
- LAST #MP $this := LAST #MP $input_schema_name; -- restore back
- RETURN $defined_event /
- ##
- #pattern_list
- (* $list!.:= #pattern_unit *)
- /IF #LEN($list) = 1 ->
- RETURN $list[1]
- ELSIF #LEN($list) = 0 ->
- RETURN <. type: empty .>
- FI;
- RETURN <. type: sequence,
- name: #IMPLODE(Sq '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $list
- .> /
- ##
- #pattern_unit
- -- check look-ahead token
- V'( $$<>';' AND $$<>')' AND $$<>'*' AND $$<>'+' AND
- $$<>'|' AND $$<>'}' AND $$<>',' AND $$<>']' AND
- $$<> BUILD AND $$<> WHEN)
- $elt:= ( #plain ! -- event name
- #alternative !
- #iteration !
- #iterator_plus !
- #set !
- #set_iterator !
- #set_iterator_plus !
- #optional !
- #when_clause !
- $x /#error( $x err2 ); FAIL/
- )
- /RETURN $elt/
- ##
- #keyword
- (WHEN ! COORDINATE ! ENSURE ! 'DO' ! 'OD' ! 'FROM') /RETURN T/
- ##
- #plain
- V'(NOT #keyword($$))
- $Id
- /RETURN <. type: plain,
- name: $Id
- .>/
- ##
- #alternative
- '(' V'($$<>'*')
- (+ [ $probability_list !.:= #probability ]
- $al!.:= #pattern_list
- +'|')
- ')'
- / IF #LEN($al) <= 1 ->
- RETURN $al[1]
- FI;
- -- return unit
- RETURN <. type: alternative,
- name: #IMPLODE(Alt '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- -- to avoid conflicts with INCUDED schemas
- body: $al,
- probability_list: $probability_list
- .>/
- ##
- #probability -- Not implemented yet <<<<<<<<<<<<<<<<<<<<<<<<
- '<<'
- ( $Float_number '>>' /RETURN $Float_number/ |
- $x /#error( $x err7 ); FAIL/
- )
- ##
- #optional
- '[' [ $probability := #probability ] $pl:= #pattern_list ']'
- / -- return unit
- RETURN <. type: optional,
- name: #IMPLODE(Opt '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $pl,
- probability: $probability
- .>/
- ##
- #iteration
- '(' '*' [ $scope:= #iteration_scope] $pl:= #pattern_list '*' ')'
- /IF NOT $scope ->
- $scope := <. lower_bound: 0, upper_bound: LAST #MP $scope .>
- FI;
- -- return unit
- RETURN <. type: iterator,
- name: #IMPLODE(Itr '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $pl,
- iteration_scope: $scope
- .>/
- ##
- #iteration_scope
- '<' $lower_bound:= #NUMBER [ '.' '.' $upper_bound:= #NUMBER ] '>'
- /IF NOT $upper_bound -> $upper_bound:= COPY($lower_bound) FI;
- RETURN <. lower_bound: $lower_bound, upper_bound: $upper_bound .>/
- ##
- #iterator_plus
- '(' '+' [$scope:= #iteration_scope] $pl:= #pattern_list '+' ')'
- /IF NOT $scope ->
- $scope := <. lower_bound: 1, upper_bound: LAST #MP $scope .>
- FI;
- -- return unit
- RETURN <. type: iterator_plus,
- name: #IMPLODE(Itp '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $pl,
- iteration_scope: $scope
- .>/
- ##
-
- #set
- '{' V'($$<>'*')
- (+ $al!.:= #pattern_list + ',') '}'
- /
- -- return unit
- RETURN <. type: set,
- name: #IMPLODE(Set '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $al -- always a list
- .>/
- ##
- #set_iterator
- '{' '*' [ $scope:= #iteration_scope] $pl:= #pattern_list '*' '}'
- /IF NOT $scope ->
- $scope := <. lower_bound: 0, upper_bound: LAST #MP $scope .>
- FI;
- -- return unit
- RETURN <. type: set_iterator,
- name: #IMPLODE(SetIt '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $pl,
- iteration_scope: $scope
- .>/
- ##
- #set_iterator_plus
- '{' '+' [ $scope:= #iteration_scope] $pl:= #pattern_list '+' '}'
- /IF NOT $scope ->
- $scope := <. lower_bound: 1, upper_bound: LAST #MP $scope .>
- FI;
- -- return unit
- RETURN <. type: set_iterator_plus,
- name: #IMPLODE(SetItp '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $pl,
- iteration_scope: $scope
- .>/
- ##
- #when_clause
- '<' '|' $pl:= #pattern_list
- WHEN (+ $wu_list !.:= #when_unit + ',') '|' '>'
- /RETURN <. type: when_clause,
- body: $pl,
- when_units: $wu_list
- .>/
- ##
- #when_unit
- [ $probability := #probability ]
- $event_name := #IDENT '==' '>' $pl:= #pattern_list
- /LAST #MP $triggering_events ++:= <. $event_name: T .>;
- RETURN <. trigger_event: $event_name,
- pattern_list: $pl,
- probability: $probability
- .>/
- ##
- ------------------------------------
- ----- composition operations -------
- ------------------------------------
- #composition_operation
- -- globals:
- ($res:= #coordinate_composition
- /LAST #MP $coordinate_ops ++:= <. $res.work: $res .>/ !
- $res:= #shared_composition
- /LAST #MP $share_all_ops ++:= <. $res.work: $res .>/ !
- $res:= #ensure_op !
- $res:= #new_event )
- /RETURN <. $res.operation: $res.work .>/
- ##
- #new_event
- NEW /#error( $ err12 )/
- ##
- #BUILD_block
- BUILD /#error( $ err12 )/
- -- add LAST #MP $variables maintenance here <<<<<<<<<<<<<<<<<<<<<<
- '{'
- (* $elts !.:= ( #composition_operation
- /LAST #MP $source_list:= NULL/ !
- #plain_attribute_declaration !
- #event_attribute_declaration )
- * ';')
- '}'
-
- ##
- #coordinate_composition
- COORDINATE
- / -- maintain the $source_list stack
- $old_source_list:= COPY(LAST #MP $source_list)/
- /$synchronization:= Synchronous/
- ['<' '!' '>' /$synchronization:= Asynchronous/]
-
- (+ $coord++:= #coordination_source
- /LAST #MP $source_list ++:= $coord/ +',')
- ('DO' ! $x /#error( $x err9 )/ )
- (+ $body !.:= ( #add_relation !
- #coordinate_composition !
- #MAP_composition !
- #shared_composition )
- ( ';' ! $x /#error( $x err11 )/ )
- +)
- ('OD' ! $x /#error( $x err10 )/ )
- /$work:= #IMPLODE( 'Coordinate_' #unique_number() '_' LAST #MP $main_schema_name);
- -- restore $source_list stack
- LAST #MP $source_list:= $old_source_list;
- RETURN <. operation: COORDINATE,
- work: $work,
- synchronization: $synchronization,
- source_list: $coord,
- body: $body .> /
- ##
- #coordination_source
- ( $var:= #variable ! $a /#error( $a err14 ); FAIL/)
- ( ':' ! $x /#error( $x err13 ); FAIL/ )
- /IF LAST #MP $source_list.$var ->
- #error( $var err19 ); FAIL
- FI/
- $pattern:= #selection_pattern
- [ 'FROM' $from:= ( 'this' !
- $v:= #variable
- /IF NOT LAST #MP $source_list.$v ->
- #error( $v err17 ); FAIL
- FI/ !
- #root_name
- )]
- -- the default for FROM is 'this'
- /IF NOT $from OR $from = this ->
- $from:= <. comp: COPY(LAST #MP $this) .>
- ELSIF NOT #TREE($from) ->
- $from:= <. var: $v .>
- FI;
- RETURN <. $var: <. selection_pattern: $pattern,
- from: $from .>
- .>/
- ##
- #variable
- $a
- /$b:= #EXPLODE($a);
- IF $b[1] <> '$' -> FAIL FI;
- $b[1]:= NULL;
- RETURN #IMPLODE($b '_variable')/
- ##
- #selection_pattern
- $plist!.:= $Id /RETURN $plist/;;
-
- '(' (+ $plist!.:= $Id + '|') ')' /RETURN $plist/
- ##
- #root_name
- V'(NOT #keyword($$))
- $Id
- /IF LAST #MP $roots.$Id OR
- ( LAST #rule $event_name = $Id AND LAST #rule $rule_type = ROOT) OR
- $Id = LAST #MP $input_schema_name ->
- RETURN <. comp: $Id .>
- ELSIF T ->
- #error( $Id err15 );
- FAIL
- FI/
- ##
- #add_relation
- ADD
- (+ $v1:= #variable
- /IF NOT LAST #MP $source_list.$v1 ->
- #error( $v1 err17 ); FAIL
- FI;/
- $relation:= ( 'IN' ! PRECEDES ! CONTAINS ! FOLLOWS ! $x /#error( $x err16 ); FAIL/)
- $v2:= #variable
- /IF NOT LAST #MP $source_list.$v2 ->
- #error( $v2 err17 ); FAIL
- FI;
- $res!.:= <. first: $v1,
- second: $v2,
- relation: $relation .>/
- + ',')
- /RETURN <. operation: ADD,
- relation_list: $res .>/
- ##
- #MAP_composition
- MAP /#error( $ err12 ); FAIL/
- ##
- #shared_composition
- (+
- (+
- $from:= ( 'this' !
- $v:= #variable
- /IF NOT LAST #MP $source_list.$v ->
- #error( $v err17 ); FAIL
- FI/ !
- #root_name
- )
- /IF $from = this ->
- $from:= <. comp: COPY(LAST #MP $this) .>
- ELSIF NOT #TREE($from) ->
- $from:= <. var: $v .>
- FI;
- $sharing_host !.:= $from/
- + #exclusive_union )
-
- /$sharing_hosts !.:= $sharing_host;
- $sharing_host:= NULL/
- + ',')
- 'SHARE' 'ALL'
- (+ $Id /$shared_events ++:= <. $Id: T .>/ + ',')
-
- /$work:= #IMPLODE( 'ShareAll_' #unique_number() '_' LAST #MP $main_schema_name);
- RETURN <. operation: SHARE_ALL,
- work: $work,
- host_list: $sharing_hosts,
- shared_events: $shared_events .>/
- ##
- #exclusive_union
- '|' '+' '|'
- ##
- #ensure_op
- ENSURE /#error( $ err12 ); FAIL/
- ##
- ------------------------------------
- ----- event attributes -------
- ------------------------------------
- #plain_attribute_declaration
- ##
- #event_attribute_declaration
- ##
- ------------------------------------------------------------------------------
- --------- 2nd pass, updates of $composites and $roots
- --------- identifying composite events
- ------------------------------------------------------------------------------
- -- put composite events into event patterns to distinguish them from plain atoms
- -- check that no recursion happens (by assembling a list of all called composites in depth)
- -- flatten iterations by scope, replacing with alternatives
- -- replace optional with alternative
- -- expand WHEN clauses macro
- -- estimate segment count
- ------------------------------------------------------------------------------
- #build_rules
- -- returns updated rule tables
- ---------------------------------
- -- Globals:
- -- $rule_id
- -- $called_composites: <* $composite_name: T *> -- composite rules called from $rule_id
- -- $inside_when -- is T when process pattern list in WHEN block
- ---------------------------------------------
- <* $rule_id: <. rule_type: $rule_type,
- work_name: $work_name,
- [build_block: $comp_op_list],
- pattern_list: $b:= #build_element
- /$res++:= <. $rule_id:
- <. rule_type: $rule_type,
- work_name: $work_name,
- pattern_list: $b,
- build_block: $comp_op_list,
- called_composites: $called_composites
- .>
- .>;
- $called_composites := NULL;
- $comp_op_list := NULL /
- .>
- *>
- /RETURN $res/
- ##
- #build_element
- -- traverses the initial tree,
- -- marks composite events to distinguish them from atoms
- -- flattening iterations by scope, replacing with alternative
- -- replacing optional with alternative
- -- checking that no recursion happens, ONLY SIMPLE RECURSION IS CHECKED
- --
- -- returns (modified) element
- ----------------
- --replaces type for 'composite', instead of "plain"
- <. type: plain,
- name: $Id .>
-
- /IF LAST #build_rules $inside_when AND LAST #MP $triggering_events.$Id ->
- #error( $Id err3); FAIL -- trigger event should not appear in pattern list
- FI;
-
- IF LAST #MP $roots.$Id ->
- #error( $Id err5); FAIL --root event should not appear in rule body
- FI;
-
- -- IF $Id = LAST #build_rules $rule_id ->
- -- detects simple recursion
- -- #error( $Id err6); FAIL --event should not appear recursively in rule body
- -- FI;
- IF LAST #MP $composites.$Id ->
- LAST #build_rules $called_composites ++:= <. $Id: T .>;
- RETURN <. type: composite,
- name: $Id
- .>
- FI;
- LAST #MP $atomic_events ++:= <. $Id: T .>;
- RETURN $ /;;
- -------------
- <. type: $type:= (sequence ! alternative),
- name: $work_name,
- body: (. (* $b !.:= #build_element *) .),
- [probability_list: $probability_list]
- .>
- /RETURN <. type: $type,
- name: $work_name,
- body: $b,
- probability_list: $probability_list
- .>/;;
- ----------------
- -- this requires to apply scope limit and transform into alternative pattern
- <. type: $type:= ( (iterator ! iterator_plus) /$new_type:= sequence/ !
- (set_iterator ! set_iterator_plus) /$new_type:= set/ ),
- name: $name,
- body: $b:= #build_element,
- iteration_scope: <. lower_bound: $lower_bound,
- upper_bound: $upper_bound .>
- .>
- / -- create alternatives for iterations lower .. upper
- $this_lower_bound := COPY($lower_bound);
- IF $this_lower_bound = 0 ->
- $new_body!.:= <. type: empty .>;
- $this_lower_bound +:=1
- FI;
- IF $this_lower_bound = 1 AND $this_lower_bound <= $upper_bound ->
- $new_body!.:= $b;
- $this_lower_bound +:=1
- FI;
-
- LOOP -- at this point $this_lower_bound > 1
- $x := COPY($this_lower_bound);
- -- now to create sequences of >=2 $b instancies
- IF $x > $upper_bound -> BREAK FI;
- -- create a sequence of $lower_bound instances of $b
- $a := NULL;
- LOOP
- IF $x = 0 -> BREAK FI;
- $a!.:= $b;
- $x +:= -1
- END;
- -- if new type = set, no permutation is needed, because all are identical
- $new_body!.:= <. type: $new_type,
- name: #IMPLODE(Ct '_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $a
- .>;
- $this_lower_bound +:= 1
- END;
-
- IF #LEN($new_body) = 1 ->
- $new_body := $new_body[1];
- RETURN $new_body
- FI;
-
- RETURN <. type: alternative,
- name: $name,
- body: $new_body .>
- /;;
-
- --------------
- <. type: optional,
- name: $name,
- body: $b:= #build_element
- .>
- /RETURN <. type: alternative,
- name: $name,
- body: (. <. type: empty .> $b .)
- .>/;;
-
- --------------
- <. type: empty .> /RETURN $/;;
-
- --------------
- <. type: set,
- name: $name,
- body: (. (* $b!.:= #build_element *) .)
- .>
- /IF #LEN($b) = 1 ->
- RETURN <. type: set,
- name: $name,
- body: $b
- .>
- ELSIF T ->
- -- find all permutations of body elements and assemble an alternative of them
- -- in fact, implement interlacing to support shared mapping
- $permutations:= #find_all_permutations($b);
- RETURN <. type: alternative,
- name: $name,
- body: $permutations .>
- FI /;;
- --------------
- <. type: when_clause /LAST #build_rules $inside_when := T/,
- body: $pl,
- when_units: $wu_list
- .>
- /LAST #build_rules $inside_when := NULL;
- -- transform WHEN pattern by applying CUT macro --<<<<<<<<<<<<<<<<<<<<<
- RETURN $ --<<<<<<<<<<<<<<<<<<<<
- /;;
- --------------
- $x /PRINT (. '****#build_element*****' build for type $x.type not yet implemented for $x .);
- RETURN EMPTY/
- ##
- #find_all_permutations
- -- find all permutations of shared events in the element_list, make a set for each,
- -- and return the list of sets
- $elt_list
- /
- -- get all index permutations
- $index_perms:= #permutations(#LEN($elt_list));
- FORALL $indexes IN $index_perms DO
- $new_list:= NULL;
- FORALL $ind IN $indexes DO
- $new_list !.:= $elt_list[$ind]
- OD;
- $new_body !.:= <. type: set,
- name: #IMPLODE( 'Set_' #unique_number()
- '_' LAST #MP $main_schema_name),
- body: $new_list
- .>
- OD;
- RETURN $new_body /
- ##
- #permutations
- -- return list of all permutations for integers 1..n
- $n
- /IF $n <= 1 -> RETURN (. (. 1 .) .) FI;
- $prev:= #permutations($n - 1);
- FORALL $p IN $prev DO
- $x:= 1;
- $len:= #LEN($p);
- -- insert n at place x in p
- LOOP
- IF $x > $len -> BREAK FI;
- $y:= 1;
- $r:= NULL;
- FORALL $e IN $p DO
- IF $y = $x -> $r !.:= $n FI;
- $r !.:= $e;
- $y +:= 1
- OD;
- $res !.:= $r;
- $x +:=1
- END;
- $item:= NULL; -- unfortunately COPY($p)!.$n does not work!
- FORALL $z IN $p DO
- $item !.:= $z
- OD;
- $item !.:= $n;
- $res !.:= $item;
- OD;
- RETURN $res /
- ##
- #detect_recursion
- -- global: $already_called
- <* $event_name: <. [ called_composites:
- /$already_called:= NULL/
- <* $callee: $x
- /$already_called ++:= <. $callee: T .>;
- IF $event_name = $callee ->
- #error( $event_name err6 ); FAIL
- FI;
-
- IF LAST #MP $new_composites.$callee.called_composites ->
- #check_recursive_call_in_depth( LAST #MP $new_composites.$callee )
- FI/
- *> ]
- .>
- *>
- ##
- #check_recursive_call_in_depth
- <. called_composites: <* $callee: $x
- /IF LAST #detect_recursion $already_called.$callee ->
- #error( $callee err6 ); FAIL
- FI;
- LAST #detect_recursion $already_called ++:= <. $callee: T .>;
- IF LAST #MP $new_composites.$callee.called_composites ->
- #check_recursive_call_in_depth( LAST #MP $new_composites.$callee )
- FI/
- *>
- .>
- ##
- #order_composites_by_dependency
- <* $event_name: <. [ called_composites:
- <* $callee: $x
- /IF LAST #MP $new_composites.$callee.called_composites ->
- #find_dependencies_in_depth( LAST #MP $new_composites.$callee )
- FI;
- IF NOT LAST #MP $already_ordered.$callee ->
- LAST #MP $already_ordered ++:= <. $callee: T .>;
- $ordered_list !.:= $callee
- FI /
- *> ]
- .>
- -- all callees have been put on the list
- /IF NOT LAST #MP $already_ordered.$event_name ->
- LAST #MP $already_ordered ++:= <. $event_name: T .>;
- $ordered_list !.:= $event_name
- FI/
- *>
- /RETURN $ordered_list/
- ##
- #find_dependencies_in_depth
- <. called_composites:
- <* $callee: $x
- /IF LAST #MP $new_composites.$callee.called_composites ->
- #find_dependencies_in_depth( LAST #MP $new_composites.$callee )
- FI;
- IF NOT LAST #MP $already_ordered.$callee ->
- LAST #MP $already_ordered ++:= <. $callee: T .>;
- $ordered_list !.:= $callee
- FI /
- *>
- .>
- ##
- #prepare_share_all
- <* $work:
- <. host_list: $sharing_hosts,
- shared_events: /$shared_events:= NULL/
- <* $event_name: $x
- /IF LAST #MP $composites.$event_name ->
- $shared_events ++:= <. $event_name: composite .>
- ELSIF LAST #MP $atomic_events.$event_name ->
- $shared_events ++:= <. $event_name: atomic .>
- ELSIF T ->
- #error( $event_name err18 ); FAIL
- FI/
- *>
- .>
- /$res ++:= <. $work:
- <. operation: SHARE_ALL,
- host_list: $sharing_hosts,
- shared_events: $shared_events .>
- .>/
- *>
- /RETURN $res/
- ##
-
- ------------- auxiliary rules -------------------
- #error
- $a /IF LAST #MP $errors_detected > 2 -> FAIL FI;
- $line := #CALL_PAS( 4 $a ) DIV 80;
- $col := #CALL_PAS( 4 $a ) MOD 80;
- MSG<< '*** error:';
- IF $line <> 0 ->
- MSG<] at $line ':' $col
- FI;
- LAST #MP $errors_detected +:= 1/
-
- ( err1 /MSG<] wrong schema name $a identifier expected/ !
- err2 /MSG<] wrong event pattern $a / !
- err3 /MSG<] trigger event $a should not appear in WHEN pattern list / !
- err4 /MSG<] detected around token $a/ !
- err5 /MSG<] root event $a should not appear in rule body/ !
- err6 /MSG<] recursion for event $a is detected/ !
- err7 /MSG<] syntax error in probability definition detected at $a/ !
- err8 /MSG<] schema name $a should be the same as input parameter/ !
- err9 /MSG<] keyword 'DO' is expected in COORDINATE when actual token is $a / !
- err10 /MSG<] keyword 'OD' is expected in COORDINATE when actual token is $a / !
- err11 /MSG<] semicolon is expected when actual token is $a / !
- err12 /MSG<] construct at token $a is not yet implemented/ !
- err13 /MSG<] ':' is expected when actual token is $a / !
- err14 /MSG<] incorrect variable name $a in the COORDINATE source / !
- err15 /MSG<] derivation for root $a should be completed before composition/ !
- err16 /MSG<] wrong relation name $a in the ADD composition/ !
- err17 /MSG<] variable name $a is undefined/ !
- err18 /MSG<] shared event $a has not been defined in any grammar rule / !
- err19 /MSG<] variable name $a has been defined twice/ !
- $any /MSG<< at token $a/
- )
- ##
- --------------------------------------------------
- #unique_number
- /LAST #MP $unique_number +:=1;
- RETURN COPY(LAST #MP $unique_number)/
- ##
|