Advertisement
rplantiko

Populate Semantic Model, using oMeta in ABAP

Jan 30th, 2012
564
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ABAP 9.17 KB | None | 0 0
  1. *&---------------------------------------------------------------------*
  2. *& Report  Z_SEMANTIC_MODEL_EXAMPLE
  3. *&
  4. *& Populating the semantic model from a rule, entered as text
  5. *& In this case, the resulting model will be a template
  6. *&
  7. *& The "real" pallets then can be filled by processing the template
  8. *&
  9. *& Requires oMeta Core (subroutine pool Z_OMETA_BASE)
  10. *& See http://pastebin.com/hunE6vsy (self contained)
  11. *&
  12. *&---------------------------------------------------------------------*
  13.  
  14. report  z_semantic_model_example.
  15.  
  16. * ----------------------------------------------------------------------
  17. * Definition of the semantic model:
  18. * A pallet can be filled with deliveries and/or other pallets
  19. * The resulting data structure consists of
  20. * - A table DELIVERY_NUMBERS of placeholder id's for all deliveries in use
  21. * - A table PALLET_NUMBERS of placeholder id's  for all pallets in use
  22. * - A table PALLETS containing the pallet contents
  23. * ----------------------------------------------------------------------
  24. types:
  25.  
  26.   ty_doc_number(10) type c,
  27.   ty_item_number(6) type c,
  28.   ty_pallet_item_type(2) type c,
  29.   ty_doc_numbers type standard table of ty_doc_number with non-unique default key,
  30.  
  31.   begin of ty_pallet_item,
  32.       pallet_no   type ty_doc_number,
  33.       item_no     type ty_item_number,
  34.       type        type ty_pallet_item_type,
  35.       content     type ty_doc_number,
  36.     end of ty_pallet_item,
  37.   ty_pallets type standard table of ty_pallet_item
  38.     with key pallet_no item_no,
  39.  
  40.    begin of ty_model,
  41.     pallet_numbers    type ty_doc_numbers,
  42.     delivery_numbers  type ty_doc_numbers,
  43.     pallets           type ty_pallets,
  44.   end of ty_model.
  45.  
  46. constants: begin of gc_pallet_item_type,
  47.   pallet   type ty_pallet_item_type value 'PA',
  48.   delivery type ty_pallet_item_type value 'DL',
  49. end of gc_pallet_item_type.
  50. * ----------------------------------------------------------------------
  51.  
  52. * A "Stop" signal
  53. class lcx_end_program definition final inheriting from cx_no_check.
  54. endclass.                    "lcx_end_program DEFINITION
  55.  
  56. load-of-program.
  57.   perform on_load.
  58.  
  59. start-of-selection.
  60.   perform start.
  61.  
  62. * ---
  63. form start.
  64.  
  65.   data: lv_rule type string,
  66.         ls_model type ty_model,
  67.         lv_parse_errors type flag value abap_undefined.
  68.  
  69.   try.
  70.  
  71.       while lv_parse_errors ne abap_false.
  72.  
  73.         perform input_rule
  74.           changing lv_rule.
  75.  
  76.         perform rule_to_model
  77.           using lv_rule
  78.           changing ls_model lv_parse_errors.
  79.  
  80.       endwhile.
  81.  
  82.       perform output_model
  83.         using ls_model.
  84.  
  85.     catch lcx_end_program.
  86.   endtry.
  87.  
  88. endform.                    "start
  89.  
  90.  
  91. * --- Apply parser to input, populating the semantic model
  92. form rule_to_model using iv_rule type string
  93.                    changing es_model type ty_model
  94.                             ev_parse_errors type flag.
  95.  
  96.   data: lv_error_code type i,
  97.         lv_result type string.
  98.  
  99.   clear es_model.
  100.  
  101. * Bind the semantic model
  102.   perform bind(z_ometa_base)
  103.     using 'pallets.model' es_model.
  104.  
  105. * Execute the parser
  106.   perform match(z_ometa_base)
  107.     using 'HandlingUnitDefinition' 'expr' iv_rule
  108.     changing lv_result lv_error_code.
  109.  
  110.   if lv_error_code <> 0.
  111.     ev_parse_errors = abap_true.
  112.     message 'The rule entered is syntactically incorrect' type 'I'.
  113.   else.
  114.     ev_parse_errors = abap_false.
  115.     perform normalize_model changing es_model.
  116.   endif.
  117.  
  118. endform.                    "rule_to_tree
  119.  
  120. * ---
  121. form normalize_model changing cs_model type ty_model.
  122.  
  123. * We would prefer sorted tables with unique key,
  124. * but JS/ABAP binding currently only allows standard tables
  125. * Therefore, sort by hand
  126.  
  127.   sort: cs_model-pallets,
  128.         cs_model-delivery_numbers,
  129.         cs_model-pallet_numbers.
  130.   delete adjacent duplicates from :
  131.         cs_model-delivery_numbers,
  132.         cs_model-pallet_numbers.
  133.  
  134. endform.                    "normalize_model
  135.  
  136. * ---
  137. form output_model using is_model type ty_model.
  138.  
  139.   call function 'RS_COMPLEX_OBJECT_EDIT'
  140.     exporting
  141.       object_name          = 'SEMANTIC MODEL'
  142.       mode                 = ' '
  143.     changing
  144.       object               = is_model
  145.     exceptions
  146.       object_not_supported = 1
  147.       others               = 2.
  148.   if sy-subrc <> 0.
  149.     message id sy-msgid type 'I' number sy-msgno
  150.       with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  151.   endif.
  152.  
  153.  
  154. endform.                    "output_model
  155.  
  156. * ---
  157. form on_load.
  158.   try.
  159.       perform set_parser.
  160.     catch lcx_end_program.
  161.       leave program.
  162.   endtry.
  163. endform.                    "on_load
  164.  
  165. * ---
  166. form set_parser.
  167.  
  168.   data: lv_grammar type string,
  169.         lv_result type string,
  170.         lv_error_code type i.
  171.  
  172.   perform get_grammar_as_string changing lv_grammar.
  173.   perform set_builder.
  174.   perform translate(z_ometa_base)
  175.     using lv_grammar
  176.     changing lv_result lv_error_code.
  177.   perform check_error using 'set parser' lv_error_code.
  178.  
  179. endform.                    "set_parser
  180.  
  181. * ---
  182. form check_error using iv_step type string
  183.                        iv_error_code type i.
  184.   data: lv_error type string.
  185.   if iv_error_code <> 0.
  186.     perform get_last_error(z_ometa_base) changing lv_error.
  187.     concatenate `Error in step '` iv_step `': `  lv_error
  188.       into lv_error respecting blanks.
  189.     message lv_error type 'I' display like 'I'.
  190.     raise exception type lcx_end_program.
  191.   endif.
  192. endform.                    "check_error
  193.  
  194. * --- Helper functions for the semantic actions
  195. form set_builder.
  196.  
  197.   data: lv_build type string,
  198.         lv_result type string,
  199.         lv_error_code type i.
  200.  
  201. * Passing the relevant parts of the input to the model
  202. * It is here where the ABAP/JS binding syntax (proxy objects) is required
  203.   concatenate
  204.     `function addDelivery(n) {`
  205.     `  return addDocNumber(pallets.model.delivery_numbers,"DL"+n);`
  206.     `  }`
  207.     `function addPallet(n) {`
  208.     `  return addDocNumber(pallets.model.pallet_numbers,"PA"+n);`
  209.     `  }`
  210.     `function buildPallet( id, content ) {`
  211.     `  var p = pallets.model.pallets;`
  212.     `  var wa, i;`
  213.     `  for (i=0;i<content.length;i++) {`
  214.     `    p.appendLine();`
  215.     `    wa = p[p.length-1];`
  216.     `    wa.pallet_no = id;`
  217.     `    wa.item_no = i+1;`
  218.     `    wa.type = content[i].substring(0,2);`
  219.     `    wa.content = content[i];`
  220.     `    }`
  221.     ` return id;`
  222.     ` }`
  223.     `function addDocNumber(table,id) {`
  224.     `  table.appendLine(); `
  225.     `  table[table.length-1] = id;`
  226.     `  return id;`
  227.     `  }`
  228.     into lv_build
  229.     separated by cl_abap_char_utilities=>cr_lf.
  230.  
  231.   perform do_it(z_ometa_base) using lv_build changing lv_result lv_error_code.
  232.   perform check_error using 'set builder' lv_error_code.
  233.  
  234. endform.                    "set_builder
  235.  
  236. * ---
  237. form input_rule changing ev_rule type string.
  238.  
  239.   data: lt_text type jstexttab.
  240.  
  241. * Memorize last input (for the error case)
  242.   statics: st_last_text type jstexttab.
  243.  
  244.   field-symbols: <lv_text> type c.
  245.  
  246.   if st_last_text is not initial.
  247.     lt_text = st_last_text.
  248.   else.
  249.     perform get_rule_proposal changing lt_text.
  250.   endif.
  251.  
  252. * Enter the packing rule in a free text window
  253.   call function 'TERM_CONTROL_EDIT'
  254.     exporting
  255.       titel          = 'Please enter rule'
  256.     tables
  257.       textlines      = lt_text
  258.     exceptions
  259.       user_cancelled = 1
  260.       others         = 2.
  261.   if sy-subrc <> 0.
  262.     if sy-msgid ne space.
  263.       message id sy-msgid type 'I' number sy-msgno
  264.         with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  265.     endif.
  266.     raise exception type lcx_end_program.
  267.   endif.
  268.  
  269.   st_last_text = lt_text.
  270.  
  271. * Map table to string
  272.   clear ev_rule.
  273.   loop at lt_text assigning <lv_text>.
  274.     if ev_rule is initial.
  275.       ev_rule = <lv_text>.
  276.     else.
  277.       concatenate ev_rule <lv_text> into ev_rule
  278.         separated by cl_abap_char_utilities=>cr_lf.
  279.     endif.
  280.   endloop.
  281.  
  282. * Ignore packing rules containing only whitespace
  283.   find regex '\S' in ev_rule.
  284.   if sy-subrc ne 0.
  285.     raise exception type lcx_end_program.
  286.   endif.
  287.  
  288. endform.                    "input_rule
  289.  
  290. * --- Some lines of oMeta code,
  291. *     defining the syntax AND semantics
  292. form get_grammar_as_string changing ev_grammar type string.
  293.  
  294.   concatenate
  295.     `ometa HandlingUnitDefinition <: Parser {`
  296.     `  expr      = fullPallet+,      `
  297.     `  delivery  = ordnum:n ( "Lieferung" | "Lief" | "LF"  )`
  298.     `          -> {addDelivery(n)},`
  299.     `  pallet  = ordnum:n ( "Palette"  | "Pal" | "SSCC" )`
  300.     `          -> {addPallet(n)},`
  301.     `  fullPallet  = pallet:s "(" content:c ")"`
  302.     `          -> { buildPallet( s, c ) },`
  303.     `  contentPart = fullPallet | delivery | pallet,`
  304.     `  content = (spaces contentPart)*:xs, `
  305.     `  ordnum  = spaces digit+:ds "." -> parseInt(ds.join(''))`
  306.     `  }`
  307.     into ev_grammar
  308.     separated by cl_abap_char_utilities=>cr_lf.
  309.  
  310. endform.                    "get_grammar_as_string
  311.  
  312. * --- Just a proposal for the text popup
  313. form get_rule_proposal changing ct_text type jstexttab.
  314.   define _add_line.
  315.     append &2 to &1.
  316.   end-of-definition.
  317.  
  318.   _add_line ct_text :
  319.     `1. Palette (`,
  320.     `  1. Lieferung`,
  321.     `  2. Palette`,
  322.     `  )`,
  323.     `2. Palette (`,
  324.     `  2. Lieferung`,
  325.     `  3. Palette ( 3. Lieferung )`,
  326.     `  )`.
  327.  
  328. endform.                    "get_rule_proposal
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement