MP2-parser.rig 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. -- MP2_parser.rig Automated model generator MP2 -> C++
  2. -- v 2.0
  3. -- Mikhail Auguston, 03/05/15
  4. -- last modified 04/05/15
  5. --
  6. -- use: parser schema_name output_file scope
  7. --
  8. -- takes the source .mp file and creates the intermediate tree
  9. --
  10. --------------------------------------------------------------
  11. #MP
  12. -- ******** Globals:
  13. -- $scope -- scope for the model
  14. -- $main_schema_name -- from the MP model, used to generate container names
  15. -- $input_schema_name -- from the parameters, should be the same
  16. -- $triggering_events: <* event_name: T *>
  17. -- events triggering WHEN, should not appear
  18. -- in patterns, but may be shared or coordinated
  19. --
  20. -- $atomic_events: <* event_name: T *> -- for generating event list in C++
  21. -- $already_ordered: <* event_name: T *> -- for #order_composites_by_dependency
  22. -- $composite_order: (. (* event_name *) .) -- retains the composite definition order
  23. -- for generating harvest() calls
  24. -- $this contains root, composite event or schema name
  25. -- for COORDINATE FROM default, reset in #rule
  26. -- $source_list: <* variable_name: pattern *> -- variables
  27. -- defined in nested compositions COORDINATE, ENSURE, NEW
  28. -- and maintained within schema or BUILD block
  29. -------------------------------------------
  30. -- these tables are produced by the 1st pass
  31. -------------------------------------------
  32. -- $composites: <* composite_event_name: <. rule_type: composite,
  33. -- work_name: work_name,
  34. -- pattern_list: $pattern_list,
  35. -- build_block: $comp_op_list .>
  36. -- *> -- composites table
  37. -- $roots: <* root_name: <. rule_type: ROOT,
  38. -- work_name: work_name,
  39. -- pattern_list: $pattern_list,
  40. -- build_block: $comp_op_list .>
  41. -- *> -- roots table
  42. --
  43. -- $coordinate_ops: <* work_name: <. operation: COORDINATE,
  44. -- work: work_name,
  45. -- synchronization: $synchronization,
  46. -- source_list: $coord,
  47. -- body: $body .> *>
  48. -- $share_all_ops: <* work_name: <. operation: SHARE_ALL,
  49. -- work: work_name,
  50. -- host_list: $sharing_hosts,
  51. -- shared_events: $shared_events .> *>
  52. -------------------------------------------
  53. -- 2nd pass results
  54. -------------------------------------------
  55. -- $new_composites: <* composite_event_name: <. rule_type: composite,
  56. -- work_name: work_name,
  57. -- pattern_list: $pattern_list,
  58. -- build_block: $comp_op_list,
  59. -- called_composites: <* $composite_name: T *> .>
  60. -- *> -- updated composites table
  61. -- $new_root_table: <* root_name: <. rule_type: ROOT,
  62. -- work_name: work_name,
  63. -- pattern_list: $pattern_list,
  64. -- build_block: $comp_op_list,
  65. -- called_composites: <* $composite_name: T *> .>
  66. -- *> -- updated roots table
  67. --
  68. -- $new_share_all_ops: <* work_name: *>
  69. -----------------------------------------
  70. -- $unique_number -- to keep work names unique
  71. -- $errors_detected -- stop reporting errors if it becomes > 3
  72. -------------------------------------------------------------
  73. $Parm:= #PARM(T); -- list of all parameters
  74. $input_schema_name := #IMPLODE( $Parm[1] );
  75. $this := $input_schema_name;
  76. $input_file := #IMPLODE( $input_schema_name '.mp');
  77. $output_file := #IMPLODE( $Parm[2] ); -- for generation phase
  78. IF $Parm[3] ->
  79. $scope := $Parm[3]; -- no need to #IMPLODE(), just take the number
  80. ELSIF T ->
  81. $scope := 1; -- default scope
  82. FI;
  83. OPEN MSG ' '; --for error messages
  84. --call C lexer
  85. $Lex:= #CALL_PAS( 35 $input_file 'L+A-U-P-C+p-m+');
  86. --PRINT $Lex; --<<<<<<<<<<<<<<
  87. MSG<< 'MPhoenix parser v.2.0 input from' $input_file scope $scope
  88. Total #LEN($Lex) tokens;
  89. $unique_number:= 0;
  90. $errors_detected:= 0;
  91. --********** 1st pass, do the parsing, $composites, $roots
  92. $complete:= #main_schema( $Lex);
  93. --*********** 2nd pass, insert/expand composite events,
  94. -- create $new_root_table, $new_composites
  95. IF $errors_detected = 0 ->
  96. $new_composites := #build_rules($composites); -- composites first
  97. #detect_recursion($new_composites);
  98. $composite_order:= #order_composites_by_dependency($new_composites);
  99. $new_root_table := #build_rules($roots);
  100. $new_share_all_ops:= #prepare_share_all($share_all_ops);
  101. FI;
  102. IF $errors_detected = 0 ->
  103. --MSG<< 'Parsing completed. Saving result in' $output_file;MSG<<;
  104. $result:= $complete ++
  105. -- the contents of $complete returned by #main_schema
  106. -- <. schema: $id_schema,
  107. -- include_list: $include_list,
  108. -- elt_list: $elt_list -- roots, composition ops
  109. -- .>
  110. <. scope: $scope,
  111. input_file: $input_file,
  112. roots: $roots, -- source for comments in C++
  113. composites: $composites, -- source for comments in C++
  114. atomic_events: $atomic_events,
  115. new_root_table: $new_root_table,
  116. new_composites: $new_composites,
  117. composite_order: $composite_order,
  118. coordinate_ops: $coordinate_ops,
  119. share_all_ops: $new_share_all_ops
  120. .>;
  121. SAVE $result $output_file;
  122. --PRINT $result; --<<<<<<<<<<<<<<<<<<<<
  123. ELSIF T -> MSG<< 'Errors detected...'
  124. FI;
  125. ##
  126. #main_schema
  127. (. SCHEMA ( $id_schema := #IDENT
  128. /LAST #MP $main_schema_name := $id_schema/ !
  129. $x /#error( $x err1 ); FAIL/
  130. )
  131. /IF (LAST #MP $input_schema_name <> $id_schema) ->
  132. #error( $id_schema err8 ); FAIL
  133. FI /
  134. (* $include_list !.:= #include_clause *)
  135. (*
  136. $elt_list !.:=
  137. ( #rule !
  138. #composition_operation
  139. /LAST #MP $source_list:= NULL/ )
  140. ( ';' ! $x /#error( $x err4 )/ )
  141. *)
  142. [ #BUILD_block ]
  143. .)
  144. /$filtered_elt_list:= #filter_elt_list($elt_list);
  145. RETURN <. schema: $id_schema,
  146. include_list: $include_list,
  147. elt_list: $filtered_elt_list -- roots, composition ops
  148. .>/
  149. ##
  150. #filter_elt_list
  151. -- to get rid of plain composite event declarations in schema
  152. -- leaving only roots and composition ops for schema's class definition
  153. (. (* ( <. composite: $a .> ! NULL ! $res !.:= $b ) *) .)
  154. /RETURN $res/
  155. ##
  156. --------------------------------------------------------------------
  157. -----1st pass--- rule syntax ---------------------------------------
  158. --------------------------------------------------------------------
  159. #include_clause
  160. INCLUDE ( $id_schema := #IDENT !
  161. $x /#error( $x err1 ); FAIL/ )
  162. ( ';' ! $x /#error( $x err4 ); FAIL/ )
  163. /RETURN $id_schema/
  164. ##
  165. #rule
  166. -- globals:
  167. -- $rule_type
  168. -- $event_name
  169. /$rule_type:= composite/ -- the default
  170. [ ROOT /$rule_type:= ROOT/]
  171. $event_name := #IDENT ':'
  172. /LAST #MP $this := $event_name; -- switch default for composition FROM
  173. $defined_event := <. $rule_type: $event_name .>/
  174. $patterns:= #pattern_list
  175. [ $build_block := #BUILD_block ]
  176. /$rule_body := <. rule_type: $rule_type,
  177. work_name: #IMPLODE( 'Comp_'
  178. #unique_number() '_' LAST #MP $main_schema_name),
  179. pattern_list: $patterns,
  180. build_block: $build_block
  181. .>;
  182. IF $rule_type = ROOT ->
  183. LAST #MP $roots ++:= <. $event_name: $rule_body .>;
  184. ELSIF T -> -- composite event definition
  185. LAST #MP $composites ++:= <. $event_name: $rule_body .>;
  186. FI;
  187. LAST #MP $this := LAST #MP $input_schema_name; -- restore back
  188. RETURN $defined_event /
  189. ##
  190. #pattern_list
  191. (* $list!.:= #pattern_unit *)
  192. /IF #LEN($list) = 1 ->
  193. RETURN $list[1]
  194. ELSIF #LEN($list) = 0 ->
  195. RETURN <. type: empty .>
  196. FI;
  197. RETURN <. type: sequence,
  198. name: #IMPLODE(Sq '_' #unique_number()
  199. '_' LAST #MP $main_schema_name),
  200. body: $list
  201. .> /
  202. ##
  203. #pattern_unit
  204. -- check look-ahead token
  205. V'( $$<>';' AND $$<>')' AND $$<>'*' AND $$<>'+' AND
  206. $$<>'|' AND $$<>'}' AND $$<>',' AND $$<>']' AND
  207. $$<> BUILD AND $$<> WHEN)
  208. $elt:= ( #plain ! -- event name
  209. #alternative !
  210. #iteration !
  211. #iterator_plus !
  212. #set !
  213. #set_iterator !
  214. #set_iterator_plus !
  215. #optional !
  216. #when_clause !
  217. $x /#error( $x err2 ); FAIL/
  218. )
  219. /RETURN $elt/
  220. ##
  221. #keyword
  222. (WHEN ! COORDINATE ! ENSURE ! 'DO' ! 'OD' ! 'FROM') /RETURN T/
  223. ##
  224. #plain
  225. V'(NOT #keyword($$))
  226. $Id
  227. /RETURN <. type: plain,
  228. name: $Id
  229. .>/
  230. ##
  231. #alternative
  232. '(' V'($$<>'*')
  233. (+ [ $probability_list !.:= #probability ]
  234. $al!.:= #pattern_list
  235. +'|')
  236. ')'
  237. / IF #LEN($al) <= 1 ->
  238. RETURN $al[1]
  239. FI;
  240. -- return unit
  241. RETURN <. type: alternative,
  242. name: #IMPLODE(Alt '_' #unique_number()
  243. '_' LAST #MP $main_schema_name),
  244. -- to avoid conflicts with INCUDED schemas
  245. body: $al,
  246. probability_list: $probability_list
  247. .>/
  248. ##
  249. #probability -- Not implemented yet <<<<<<<<<<<<<<<<<<<<<<<<
  250. '<<'
  251. ( $Float_number '>>' /RETURN $Float_number/ |
  252. $x /#error( $x err7 ); FAIL/
  253. )
  254. ##
  255. #optional
  256. '[' [ $probability := #probability ] $pl:= #pattern_list ']'
  257. / -- return unit
  258. RETURN <. type: optional,
  259. name: #IMPLODE(Opt '_' #unique_number()
  260. '_' LAST #MP $main_schema_name),
  261. body: $pl,
  262. probability: $probability
  263. .>/
  264. ##
  265. #iteration
  266. '(' '*' [ $scope:= #iteration_scope] $pl:= #pattern_list '*' ')'
  267. /IF NOT $scope ->
  268. $scope := <. lower_bound: 0, upper_bound: LAST #MP $scope .>
  269. FI;
  270. -- return unit
  271. RETURN <. type: iterator,
  272. name: #IMPLODE(Itr '_' #unique_number()
  273. '_' LAST #MP $main_schema_name),
  274. body: $pl,
  275. iteration_scope: $scope
  276. .>/
  277. ##
  278. #iteration_scope
  279. '<' $lower_bound:= #NUMBER [ '.' '.' $upper_bound:= #NUMBER ] '>'
  280. /IF NOT $upper_bound -> $upper_bound:= COPY($lower_bound) FI;
  281. RETURN <. lower_bound: $lower_bound, upper_bound: $upper_bound .>/
  282. ##
  283. #iterator_plus
  284. '(' '+' [$scope:= #iteration_scope] $pl:= #pattern_list '+' ')'
  285. /IF NOT $scope ->
  286. $scope := <. lower_bound: 1, upper_bound: LAST #MP $scope .>
  287. FI;
  288. -- return unit
  289. RETURN <. type: iterator_plus,
  290. name: #IMPLODE(Itp '_' #unique_number()
  291. '_' LAST #MP $main_schema_name),
  292. body: $pl,
  293. iteration_scope: $scope
  294. .>/
  295. ##
  296. #set
  297. '{' V'($$<>'*')
  298. (+ $al!.:= #pattern_list + ',') '}'
  299. /
  300. -- return unit
  301. RETURN <. type: set,
  302. name: #IMPLODE(Set '_' #unique_number()
  303. '_' LAST #MP $main_schema_name),
  304. body: $al -- always a list
  305. .>/
  306. ##
  307. #set_iterator
  308. '{' '*' [ $scope:= #iteration_scope] $pl:= #pattern_list '*' '}'
  309. /IF NOT $scope ->
  310. $scope := <. lower_bound: 0, upper_bound: LAST #MP $scope .>
  311. FI;
  312. -- return unit
  313. RETURN <. type: set_iterator,
  314. name: #IMPLODE(SetIt '_' #unique_number()
  315. '_' LAST #MP $main_schema_name),
  316. body: $pl,
  317. iteration_scope: $scope
  318. .>/
  319. ##
  320. #set_iterator_plus
  321. '{' '+' [ $scope:= #iteration_scope] $pl:= #pattern_list '+' '}'
  322. /IF NOT $scope ->
  323. $scope := <. lower_bound: 1, upper_bound: LAST #MP $scope .>
  324. FI;
  325. -- return unit
  326. RETURN <. type: set_iterator_plus,
  327. name: #IMPLODE(SetItp '_' #unique_number()
  328. '_' LAST #MP $main_schema_name),
  329. body: $pl,
  330. iteration_scope: $scope
  331. .>/
  332. ##
  333. #when_clause
  334. '<' '|' $pl:= #pattern_list
  335. WHEN (+ $wu_list !.:= #when_unit + ',') '|' '>'
  336. /RETURN <. type: when_clause,
  337. body: $pl,
  338. when_units: $wu_list
  339. .>/
  340. ##
  341. #when_unit
  342. [ $probability := #probability ]
  343. $event_name := #IDENT '==' '>' $pl:= #pattern_list
  344. /LAST #MP $triggering_events ++:= <. $event_name: T .>;
  345. RETURN <. trigger_event: $event_name,
  346. pattern_list: $pl,
  347. probability: $probability
  348. .>/
  349. ##
  350. ------------------------------------
  351. ----- composition operations -------
  352. ------------------------------------
  353. #composition_operation
  354. -- globals:
  355. ($res:= #coordinate_composition
  356. /LAST #MP $coordinate_ops ++:= <. $res.work: $res .>/ !
  357. $res:= #shared_composition
  358. /LAST #MP $share_all_ops ++:= <. $res.work: $res .>/ !
  359. $res:= #ensure_op !
  360. $res:= #new_event )
  361. /RETURN <. $res.operation: $res.work .>/
  362. ##
  363. #new_event
  364. NEW /#error( $ err12 )/
  365. ##
  366. #BUILD_block
  367. BUILD /#error( $ err12 )/
  368. -- add LAST #MP $variables maintenance here <<<<<<<<<<<<<<<<<<<<<<
  369. '{'
  370. (* $elts !.:= ( #composition_operation
  371. /LAST #MP $source_list:= NULL/ !
  372. #plain_attribute_declaration !
  373. #event_attribute_declaration )
  374. * ';')
  375. '}'
  376. ##
  377. #coordinate_composition
  378. COORDINATE
  379. / -- maintain the $source_list stack
  380. $old_source_list:= COPY(LAST #MP $source_list)/
  381. /$synchronization:= Synchronous/
  382. ['<' '!' '>' /$synchronization:= Asynchronous/]
  383. (+ $coord++:= #coordination_source
  384. /LAST #MP $source_list ++:= $coord/ +',')
  385. ('DO' ! $x /#error( $x err9 )/ )
  386. (+ $body !.:= ( #add_relation !
  387. #coordinate_composition !
  388. #MAP_composition !
  389. #shared_composition )
  390. ( ';' ! $x /#error( $x err11 )/ )
  391. +)
  392. ('OD' ! $x /#error( $x err10 )/ )
  393. /$work:= #IMPLODE( 'Coordinate_' #unique_number() '_' LAST #MP $main_schema_name);
  394. -- restore $source_list stack
  395. LAST #MP $source_list:= $old_source_list;
  396. RETURN <. operation: COORDINATE,
  397. work: $work,
  398. synchronization: $synchronization,
  399. source_list: $coord,
  400. body: $body .> /
  401. ##
  402. #coordination_source
  403. ( $var:= #variable ! $a /#error( $a err14 ); FAIL/)
  404. ( ':' ! $x /#error( $x err13 ); FAIL/ )
  405. /IF LAST #MP $source_list.$var ->
  406. #error( $var err19 ); FAIL
  407. FI/
  408. $pattern:= #selection_pattern
  409. [ 'FROM' $from:= ( 'this' !
  410. $v:= #variable
  411. /IF NOT LAST #MP $source_list.$v ->
  412. #error( $v err17 ); FAIL
  413. FI/ !
  414. #root_name
  415. )]
  416. -- the default for FROM is 'this'
  417. /IF NOT $from OR $from = this ->
  418. $from:= <. comp: COPY(LAST #MP $this) .>
  419. ELSIF NOT #TREE($from) ->
  420. $from:= <. var: $v .>
  421. FI;
  422. RETURN <. $var: <. selection_pattern: $pattern,
  423. from: $from .>
  424. .>/
  425. ##
  426. #variable
  427. $a
  428. /$b:= #EXPLODE($a);
  429. IF $b[1] <> '$' -> FAIL FI;
  430. $b[1]:= NULL;
  431. RETURN #IMPLODE($b '_variable')/
  432. ##
  433. #selection_pattern
  434. $plist!.:= $Id /RETURN $plist/;;
  435. '(' (+ $plist!.:= $Id + '|') ')' /RETURN $plist/
  436. ##
  437. #root_name
  438. V'(NOT #keyword($$))
  439. $Id
  440. /IF LAST #MP $roots.$Id OR
  441. ( LAST #rule $event_name = $Id AND LAST #rule $rule_type = ROOT) OR
  442. $Id = LAST #MP $input_schema_name ->
  443. RETURN <. comp: $Id .>
  444. ELSIF T ->
  445. #error( $Id err15 );
  446. FAIL
  447. FI/
  448. ##
  449. #add_relation
  450. ADD
  451. (+ $v1:= #variable
  452. /IF NOT LAST #MP $source_list.$v1 ->
  453. #error( $v1 err17 ); FAIL
  454. FI;/
  455. $relation:= ( 'IN' ! PRECEDES ! CONTAINS ! FOLLOWS ! $x /#error( $x err16 ); FAIL/)
  456. $v2:= #variable
  457. /IF NOT LAST #MP $source_list.$v2 ->
  458. #error( $v2 err17 ); FAIL
  459. FI;
  460. $res!.:= <. first: $v1,
  461. second: $v2,
  462. relation: $relation .>/
  463. + ',')
  464. /RETURN <. operation: ADD,
  465. relation_list: $res .>/
  466. ##
  467. #MAP_composition
  468. MAP /#error( $ err12 ); FAIL/
  469. ##
  470. #shared_composition
  471. (+
  472. (+
  473. $from:= ( 'this' !
  474. $v:= #variable
  475. /IF NOT LAST #MP $source_list.$v ->
  476. #error( $v err17 ); FAIL
  477. FI/ !
  478. #root_name
  479. )
  480. /IF $from = this ->
  481. $from:= <. comp: COPY(LAST #MP $this) .>
  482. ELSIF NOT #TREE($from) ->
  483. $from:= <. var: $v .>
  484. FI;
  485. $sharing_host !.:= $from/
  486. + #exclusive_union )
  487. /$sharing_hosts !.:= $sharing_host;
  488. $sharing_host:= NULL/
  489. + ',')
  490. 'SHARE' 'ALL'
  491. (+ $Id /$shared_events ++:= <. $Id: T .>/ + ',')
  492. /$work:= #IMPLODE( 'ShareAll_' #unique_number() '_' LAST #MP $main_schema_name);
  493. RETURN <. operation: SHARE_ALL,
  494. work: $work,
  495. host_list: $sharing_hosts,
  496. shared_events: $shared_events .>/
  497. ##
  498. #exclusive_union
  499. '|' '+' '|'
  500. ##
  501. #ensure_op
  502. ENSURE /#error( $ err12 ); FAIL/
  503. ##
  504. ------------------------------------
  505. ----- event attributes -------
  506. ------------------------------------
  507. #plain_attribute_declaration
  508. ##
  509. #event_attribute_declaration
  510. ##
  511. ------------------------------------------------------------------------------
  512. --------- 2nd pass, updates of $composites and $roots
  513. --------- identifying composite events
  514. ------------------------------------------------------------------------------
  515. -- put composite events into event patterns to distinguish them from plain atoms
  516. -- check that no recursion happens (by assembling a list of all called composites in depth)
  517. -- flatten iterations by scope, replacing with alternatives
  518. -- replace optional with alternative
  519. -- expand WHEN clauses macro
  520. -- estimate segment count
  521. ------------------------------------------------------------------------------
  522. #build_rules
  523. -- returns updated rule tables
  524. ---------------------------------
  525. -- Globals:
  526. -- $rule_id
  527. -- $called_composites: <* $composite_name: T *> -- composite rules called from $rule_id
  528. -- $inside_when -- is T when process pattern list in WHEN block
  529. ---------------------------------------------
  530. <* $rule_id: <. rule_type: $rule_type,
  531. work_name: $work_name,
  532. [build_block: $comp_op_list],
  533. pattern_list: $b:= #build_element
  534. /$res++:= <. $rule_id:
  535. <. rule_type: $rule_type,
  536. work_name: $work_name,
  537. pattern_list: $b,
  538. build_block: $comp_op_list,
  539. called_composites: $called_composites
  540. .>
  541. .>;
  542. $called_composites := NULL;
  543. $comp_op_list := NULL /
  544. .>
  545. *>
  546. /RETURN $res/
  547. ##
  548. #build_element
  549. -- traverses the initial tree,
  550. -- marks composite events to distinguish them from atoms
  551. -- flattening iterations by scope, replacing with alternative
  552. -- replacing optional with alternative
  553. -- checking that no recursion happens, ONLY SIMPLE RECURSION IS CHECKED
  554. --
  555. -- returns (modified) element
  556. ----------------
  557. --replaces type for 'composite', instead of "plain"
  558. <. type: plain,
  559. name: $Id .>
  560. /IF LAST #build_rules $inside_when AND LAST #MP $triggering_events.$Id ->
  561. #error( $Id err3); FAIL -- trigger event should not appear in pattern list
  562. FI;
  563. IF LAST #MP $roots.$Id ->
  564. #error( $Id err5); FAIL --root event should not appear in rule body
  565. FI;
  566. -- IF $Id = LAST #build_rules $rule_id ->
  567. -- detects simple recursion
  568. -- #error( $Id err6); FAIL --event should not appear recursively in rule body
  569. -- FI;
  570. IF LAST #MP $composites.$Id ->
  571. LAST #build_rules $called_composites ++:= <. $Id: T .>;
  572. RETURN <. type: composite,
  573. name: $Id
  574. .>
  575. FI;
  576. LAST #MP $atomic_events ++:= <. $Id: T .>;
  577. RETURN $ /;;
  578. -------------
  579. <. type: $type:= (sequence ! alternative),
  580. name: $work_name,
  581. body: (. (* $b !.:= #build_element *) .),
  582. [probability_list: $probability_list]
  583. .>
  584. /RETURN <. type: $type,
  585. name: $work_name,
  586. body: $b,
  587. probability_list: $probability_list
  588. .>/;;
  589. ----------------
  590. -- this requires to apply scope limit and transform into alternative pattern
  591. <. type: $type:= ( (iterator ! iterator_plus) /$new_type:= sequence/ !
  592. (set_iterator ! set_iterator_plus) /$new_type:= set/ ),
  593. name: $name,
  594. body: $b:= #build_element,
  595. iteration_scope: <. lower_bound: $lower_bound,
  596. upper_bound: $upper_bound .>
  597. .>
  598. / -- create alternatives for iterations lower .. upper
  599. $this_lower_bound := COPY($lower_bound);
  600. IF $this_lower_bound = 0 ->
  601. $new_body!.:= <. type: empty .>;
  602. $this_lower_bound +:=1
  603. FI;
  604. IF $this_lower_bound = 1 AND $this_lower_bound <= $upper_bound ->
  605. $new_body!.:= $b;
  606. $this_lower_bound +:=1
  607. FI;
  608. LOOP -- at this point $this_lower_bound > 1
  609. $x := COPY($this_lower_bound);
  610. -- now to create sequences of >=2 $b instancies
  611. IF $x > $upper_bound -> BREAK FI;
  612. -- create a sequence of $lower_bound instances of $b
  613. $a := NULL;
  614. LOOP
  615. IF $x = 0 -> BREAK FI;
  616. $a!.:= $b;
  617. $x +:= -1
  618. END;
  619. -- if new type = set, no permutation is needed, because all are identical
  620. $new_body!.:= <. type: $new_type,
  621. name: #IMPLODE(Ct '_' #unique_number()
  622. '_' LAST #MP $main_schema_name),
  623. body: $a
  624. .>;
  625. $this_lower_bound +:= 1
  626. END;
  627. IF #LEN($new_body) = 1 ->
  628. $new_body := $new_body[1];
  629. RETURN $new_body
  630. FI;
  631. RETURN <. type: alternative,
  632. name: $name,
  633. body: $new_body .>
  634. /;;
  635. --------------
  636. <. type: optional,
  637. name: $name,
  638. body: $b:= #build_element
  639. .>
  640. /RETURN <. type: alternative,
  641. name: $name,
  642. body: (. <. type: empty .> $b .)
  643. .>/;;
  644. --------------
  645. <. type: empty .> /RETURN $/;;
  646. --------------
  647. <. type: set,
  648. name: $name,
  649. body: (. (* $b!.:= #build_element *) .)
  650. .>
  651. /IF #LEN($b) = 1 ->
  652. RETURN <. type: set,
  653. name: $name,
  654. body: $b
  655. .>
  656. ELSIF T ->
  657. -- find all permutations of body elements and assemble an alternative of them
  658. -- in fact, implement interlacing to support shared mapping
  659. $permutations:= #find_all_permutations($b);
  660. RETURN <. type: alternative,
  661. name: $name,
  662. body: $permutations .>
  663. FI /;;
  664. --------------
  665. <. type: when_clause /LAST #build_rules $inside_when := T/,
  666. body: $pl,
  667. when_units: $wu_list
  668. .>
  669. /LAST #build_rules $inside_when := NULL;
  670. -- transform WHEN pattern by applying CUT macro --<<<<<<<<<<<<<<<<<<<<<
  671. RETURN $ --<<<<<<<<<<<<<<<<<<<<
  672. /;;
  673. --------------
  674. $x /PRINT (. '****#build_element*****' build for type $x.type not yet implemented for $x .);
  675. RETURN EMPTY/
  676. ##
  677. #find_all_permutations
  678. -- find all permutations of shared events in the element_list, make a set for each,
  679. -- and return the list of sets
  680. $elt_list
  681. /
  682. -- get all index permutations
  683. $index_perms:= #permutations(#LEN($elt_list));
  684. FORALL $indexes IN $index_perms DO
  685. $new_list:= NULL;
  686. FORALL $ind IN $indexes DO
  687. $new_list !.:= $elt_list[$ind]
  688. OD;
  689. $new_body !.:= <. type: set,
  690. name: #IMPLODE( 'Set_' #unique_number()
  691. '_' LAST #MP $main_schema_name),
  692. body: $new_list
  693. .>
  694. OD;
  695. RETURN $new_body /
  696. ##
  697. #permutations
  698. -- return list of all permutations for integers 1..n
  699. $n
  700. /IF $n <= 1 -> RETURN (. (. 1 .) .) FI;
  701. $prev:= #permutations($n - 1);
  702. FORALL $p IN $prev DO
  703. $x:= 1;
  704. $len:= #LEN($p);
  705. -- insert n at place x in p
  706. LOOP
  707. IF $x > $len -> BREAK FI;
  708. $y:= 1;
  709. $r:= NULL;
  710. FORALL $e IN $p DO
  711. IF $y = $x -> $r !.:= $n FI;
  712. $r !.:= $e;
  713. $y +:= 1
  714. OD;
  715. $res !.:= $r;
  716. $x +:=1
  717. END;
  718. $item:= NULL; -- unfortunately COPY($p)!.$n does not work!
  719. FORALL $z IN $p DO
  720. $item !.:= $z
  721. OD;
  722. $item !.:= $n;
  723. $res !.:= $item;
  724. OD;
  725. RETURN $res /
  726. ##
  727. #detect_recursion
  728. -- global: $already_called
  729. <* $event_name: <. [ called_composites:
  730. /$already_called:= NULL/
  731. <* $callee: $x
  732. /$already_called ++:= <. $callee: T .>;
  733. IF $event_name = $callee ->
  734. #error( $event_name err6 ); FAIL
  735. FI;
  736. IF LAST #MP $new_composites.$callee.called_composites ->
  737. #check_recursive_call_in_depth( LAST #MP $new_composites.$callee )
  738. FI/
  739. *> ]
  740. .>
  741. *>
  742. ##
  743. #check_recursive_call_in_depth
  744. <. called_composites: <* $callee: $x
  745. /IF LAST #detect_recursion $already_called.$callee ->
  746. #error( $callee err6 ); FAIL
  747. FI;
  748. LAST #detect_recursion $already_called ++:= <. $callee: T .>;
  749. IF LAST #MP $new_composites.$callee.called_composites ->
  750. #check_recursive_call_in_depth( LAST #MP $new_composites.$callee )
  751. FI/
  752. *>
  753. .>
  754. ##
  755. #order_composites_by_dependency
  756. <* $event_name: <. [ called_composites:
  757. <* $callee: $x
  758. /IF LAST #MP $new_composites.$callee.called_composites ->
  759. #find_dependencies_in_depth( LAST #MP $new_composites.$callee )
  760. FI;
  761. IF NOT LAST #MP $already_ordered.$callee ->
  762. LAST #MP $already_ordered ++:= <. $callee: T .>;
  763. $ordered_list !.:= $callee
  764. FI /
  765. *> ]
  766. .>
  767. -- all callees have been put on the list
  768. /IF NOT LAST #MP $already_ordered.$event_name ->
  769. LAST #MP $already_ordered ++:= <. $event_name: T .>;
  770. $ordered_list !.:= $event_name
  771. FI/
  772. *>
  773. /RETURN $ordered_list/
  774. ##
  775. #find_dependencies_in_depth
  776. <. called_composites:
  777. <* $callee: $x
  778. /IF LAST #MP $new_composites.$callee.called_composites ->
  779. #find_dependencies_in_depth( LAST #MP $new_composites.$callee )
  780. FI;
  781. IF NOT LAST #MP $already_ordered.$callee ->
  782. LAST #MP $already_ordered ++:= <. $callee: T .>;
  783. $ordered_list !.:= $callee
  784. FI /
  785. *>
  786. .>
  787. ##
  788. #prepare_share_all
  789. <* $work:
  790. <. host_list: $sharing_hosts,
  791. shared_events: /$shared_events:= NULL/
  792. <* $event_name: $x
  793. /IF LAST #MP $composites.$event_name ->
  794. $shared_events ++:= <. $event_name: composite .>
  795. ELSIF LAST #MP $atomic_events.$event_name ->
  796. $shared_events ++:= <. $event_name: atomic .>
  797. ELSIF T ->
  798. #error( $event_name err18 ); FAIL
  799. FI/
  800. *>
  801. .>
  802. /$res ++:= <. $work:
  803. <. operation: SHARE_ALL,
  804. host_list: $sharing_hosts,
  805. shared_events: $shared_events .>
  806. .>/
  807. *>
  808. /RETURN $res/
  809. ##
  810. ------------- auxiliary rules -------------------
  811. #error
  812. $a /IF LAST #MP $errors_detected > 2 -> FAIL FI;
  813. $line := #CALL_PAS( 4 $a ) DIV 80;
  814. $col := #CALL_PAS( 4 $a ) MOD 80;
  815. MSG<< '*** error:';
  816. IF $line <> 0 ->
  817. MSG<] at $line ':' $col
  818. FI;
  819. LAST #MP $errors_detected +:= 1/
  820. ( err1 /MSG<] wrong schema name $a identifier expected/ !
  821. err2 /MSG<] wrong event pattern $a / !
  822. err3 /MSG<] trigger event $a should not appear in WHEN pattern list / !
  823. err4 /MSG<] detected around token $a/ !
  824. err5 /MSG<] root event $a should not appear in rule body/ !
  825. err6 /MSG<] recursion for event $a is detected/ !
  826. err7 /MSG<] syntax error in probability definition detected at $a/ !
  827. err8 /MSG<] schema name $a should be the same as input parameter/ !
  828. err9 /MSG<] keyword 'DO' is expected in COORDINATE when actual token is $a / !
  829. err10 /MSG<] keyword 'OD' is expected in COORDINATE when actual token is $a / !
  830. err11 /MSG<] semicolon is expected when actual token is $a / !
  831. err12 /MSG<] construct at token $a is not yet implemented/ !
  832. err13 /MSG<] ':' is expected when actual token is $a / !
  833. err14 /MSG<] incorrect variable name $a in the COORDINATE source / !
  834. err15 /MSG<] derivation for root $a should be completed before composition/ !
  835. err16 /MSG<] wrong relation name $a in the ADD composition/ !
  836. err17 /MSG<] variable name $a is undefined/ !
  837. err18 /MSG<] shared event $a has not been defined in any grammar rule / !
  838. err19 /MSG<] variable name $a has been defined twice/ !
  839. $any /MSG<< at token $a/
  840. )
  841. ##
  842. --------------------------------------------------
  843. #unique_number
  844. /LAST #MP $unique_number +:=1;
  845. RETURN COPY(LAST #MP $unique_number)/
  846. ##