source: ruby/trunk/lib/adl_parser/lib/parser.y @ 265

Last change on this file since 265 was 265, checked in by Tatsukawa, Akimichi, 11 years ago

refactoring adl scanners in object-oriented way in progress

File size: 66.7 KB
Line 
1
2class OpenEHR::ADL::Parser
3
4#options omit_action_call
5
6prechigh
7
8  nonassoc UMINUS UPLUS
9  left '*' '/'
10  left '+' '-'
11
12  nonassoc SYM_EQ
13  nonassoc SYM_NE
14  nonassoc SYM_LT
15  nonassoc SYM_START_DBLOCK
16  nonassoc SYM_START_CBLOCK
17  nonassoc SYM_GT
18  nonassoc SYM_END_CBLOCK
19  nonassoc SYM_END_DBLOCK
20  nonassoc SYM_LE
21  nonassoc SYM_GE
22
23preclow
24
25
26rule
27### http://svn.openehr.org/ref_impl_eiffel/TRUNK/components/adl_parser/src/syntax/adl/parser/adl_validator.y
28
29input: archetype EOF
30  {
31    result = val[0]
32  }
33  | error
34
35archetype: arch_identification arch_specialisation arch_concept arch_language arch_description arch_definition arch_invariant arch_ontology
36  {
37    assert_at(__FILE__,__LINE__) do
38      val[4].instance_of?(OpenEHR::AM::Archetype::Archetype_Description::ARCHETYPE_DESCRIPTION) and val[5].instance_of?(OpenEHR::AM::Archetype::Constraint_Model::C_COMPLEX_OBJECT) and val[7].instance_of?(OpenEHR::AM::Archetype::Ontology::ARCHETYPE_ONTOLOGY)
39    end
40   
41    archetype_id = val[0][:archetype_id]
42    parent_archtype_id = val[1][:parent_archtype_id] if val[1]
43    adl_version = val[0][:arch_head][:arch_meta_data][:adl_version]
44    concept = val[2]
45    language = val[3][:arch_language]
46    archetype = OpenEHR::AM::Archetype::ARCHETYPE.create(
47                                                         :archetype_id => archetype_id,
48                                                         :parent_archtype_id => parent_archtype_id,
49                                                         :adl_version => adl_version,
50                                                         :concept => concept,
51                                                         :description => val[4],
52                                                         :definition => val[5],
53                                                         :ontology => val[7]
54                                                         ) do |archetype|
55      archetype.original_language = language
56    end
57    @@logger.debug("#{__FILE__}:#{__LINE__}: archetype = #{archetype} at #{@filename}:#{@lineno}")
58    result = archetype
59  }
60
61
62arch_identification: arch_head V_ARCHETYPE_ID
63  {
64    result = {:arch_head => val[0], :archetype_id => val[1] }
65  }
66  | SYM_ARCHETYPE error
67  {
68    raise
69  }
70
71arch_head: SYM_ARCHETYPE
72  {
73    result = {:arch_meta_data => nil }
74  }
75  | SYM_ARCHETYPE arch_meta_data
76  {
77    result = val[1]
78  }
79
80arch_meta_data: Left_parenthesis_code arch_meta_data_items Right_parenthesis_code
81  {
82    result = {:arch_meta_data => val[1] }
83  }
84
85arch_meta_data_items: arch_meta_data_item
86  {
87    result = val[0]
88  }
89  | arch_meta_data_items Semicolon_code arch_meta_data_item
90  {
91    result = val[0].merge(val[2])
92  }
93
94
95arch_meta_data_item: SYM_ADL_VERSION SYM_EQ V_VERSION_STRING
96  {
97    result = {:adl_version => val[2], :is_controlled => false }
98  }
99  | SYM_IS_CONTROLLED
100  {
101    result = {:is_controlled => true }
102  }
103
104# Define specialization in which its constraints are narrower than those of the parent.
105# Any data created via the use of the specialized archetype shall be conformant both to it and its parent.
106arch_specialisation: #-- empty is ok
107  | SYM_SPECIALIZE V_ARCHETYPE_ID
108  {
109    result = {:parent_archtype_id => val[1]}
110  }
111  | SYM_SPECIALIZE error
112
113arch_concept: SYM_CONCEPT V_LOCAL_TERM_CODE_REF
114  {
115    result = {:arch_concept => val[1] }
116  }
117  | SYM_CONCEPT error
118
119#arch_language: #-- empty is ok for ADL 1.4 tools
120#    | SYM_LANGUAGE V_DADL_TEXT
121#  | SYM_LANGUAGE error
122
123arch_language: #-- empty is ok for ADL 1.4 tools
124  {
125    result = {:arch_language => nil}
126  }
127    | SYM_LANGUAGE dadl_section
128  {
129    result = {:arch_language => val[1]}
130  }
131  | SYM_LANGUAGE error
132
133#arch_description: #-- no meta-data ok
134#    | SYM_DESCRIPTION V_DADL_TEXT
135#  | SYM_DESCRIPTION error
136
137arch_description: #-- no meta-data ok
138    | SYM_DESCRIPTION dadl_section
139  {
140    result = OpenEHR::AM::Archetype::Archetype_Description::ARCHETYPE_DESCRIPTION.new(:details => val[1])
141  }
142  | SYM_DESCRIPTION error
143 
144#arch_definition: SYM_DEFINITION V_CADL_TEXT
145#  | SYM_DEFINITION error
146arch_definition: SYM_DEFINITION cadl_section
147  {
148    result = val[1]
149  }
150  | SYM_DEFINITION error
151
152
153### cADL section
154cadl_section: c_complex_object
155  {
156    assert_at(__FILE__,__LINE__){val[0].instance_of?(OpenEHR::AM::Archetype::Constraint_Model::C_COMPLEX_OBJECT)}
157    @@logger.debug("#{__FILE__}:#{__LINE__}: c_complex_object = #{val[0]} at #{@filename}:#{@lineno}")
158    result = val[0]
159  }
160  | assertions
161  {
162    result = val[0]
163  }
164#  | error
165
166#c_complex_object: c_complex_object_head SYM_MATCHES SYM_START_CBLOCK c_complex_object_body SYM_END_CBLOCK
167c_complex_object: c_complx_object_head SYM_MATCHES START_REGEXP_BLOCK REGEXP_BODY END_REGEXP_BLOCK # added by akimichi
168  {
169    result = OpenEHR::AM::Archetype::Constraint_Model::C_COMPLEX_OBJECT.create(:attributes => val[3]) do |c_complex_object|
170      c_complex_object.node_id = val[0][:c_complex_object_id][:local_term_code_ref]
171      c_complex_object.rm_type_name = val[0][:c_complex_object_id][:type_identifier]
172      c_complex_object.occurrences = val[0][:c_occurrences]
173    end
174  }
175    | c_complex_object_head SYM_MATCHES SYM_START_CBLOCK c_complex_object_body SYM_END_CBLOCK
176  {
177    result = OpenEHR::AM::Archetype::Constraint_Model::C_COMPLEX_OBJECT.create(:attributes => val[3]) do |c_complex_object|
178      c_complex_object.node_id = val[0][:c_complex_object_id][:local_term_code_ref]
179      c_complex_object.rm_type_name = val[0][:c_complex_object_id][:type_identifier]
180      c_complex_object.occurrences = val[0][:c_occurrences]
181    end
182  }
183#    | c_complex_object_head error SYM_END_CBLOCK
184#    | c_complex_object_head SYM_MATCHES SYM_START_CBLOCK c_complex_object_body c_invariants SYM_END_CBLOCK
185
186c_complex_object_head: c_complex_object_id c_occurrences
187  {
188    result = {:c_complex_object_id => val[0], :c_occurrences => val[1]}
189  }
190
191c_complex_object_id: type_identifier
192  {
193    result = {:type_identifier => val[0]}
194  }
195  | type_identifier V_LOCAL_TERM_CODE_REF
196  {
197    result = {:type_identifier => val[0], :local_term_code_ref => val[1]}
198  }
199
200c_complex_object_body: c_any #-- used to indicate that any value of a type is ok
201  | c_attributes
202  {
203    result = OpenEHR::AM::Archetype::Constraint_Model::C_COMPLEX_OBJECT.new(:attributes => val[0])
204  }
205
206
207#------------------------- node types -----------------------
208### http://www.openehr.org/svn/ref_impl_eiffel/TRUNK/components/adl_parser/src/syntax/cadl/parser/cadl_validator.html
209### c_object:  c_complex_object
210### | archetype_internal_ref
211### | archetype_slot
212### | constraint_ref
213### | c_code_phrase
214### | c_ordinal
215### | c_primitive_object
216### | V_C_DOMAIN_TYPE
217### | ERR_C_DOMAIN_TYPE
218### | error
219c_object: c_complex_object
220  {
221    @@logger.debug("#{__FILE__}:#{__LINE__}: c_complex_object = #{val[0].inspect} at #{@filename}:#{@lineno}")
222    result = val[0]
223  }
224  | archetype_internal_ref
225  {
226    result = OpenEHR::AM::Archetype::Constraint_Model::ARCHETYPE_INTERNAL_REF.create do |archetype_internal_ref|
227      archetype_internal_ref.target_path = val[0][:absolute_path]
228      archetype_internal_ref.rm_type_name = val[0][:type_identifier]
229      archetype_internal_ref.occurrences = val[0][:c_occurrences]
230    end
231  }
232  | archetype_slot
233  {
234    result = val[0]
235  }
236  | constraint_ref
237  {
238    result = OpenEHR::AM::Archetype::Constraint_Model::CONSTRAINT_REF.create do |constraint_ref|
239      constraint_ref.reference = val[0]
240    end
241  }
242  | c_code_phrase
243  {
244    result = val[0]
245  }
246  | c_ordinal
247  {
248    result = val[0]
249  }
250  | c_primitive_object
251  {
252    result = val[0]
253  }
254  | v_c_domain_type
255  {
256    result = val[0]
257  }
258
259#  | v_c_domain_type
260#  | V_C_DOMAIN_TYPE
261  #   this is an attempt to match a dADL section inside cADL. It will
262  #   probably never work 100% properly since there can be '>' inside "||"
263  #   ranges, and also strings containing any character, e.g. units string
264  #   contining "{}" chars. The real solution is to use the dADL parser on
265  #   the buffer from the current point on and be able to fast-forward the
266  #   cursor to the last character matched by the dADL scanner
267  | ERR_C_DOMAIN_TYPE
268  | error
269
270v_c_domain_type: START_V_C_DOMAIN_TYPE_BLOCK dadl_section END_V_C_DOMAIN_TYPE_BLOCK
271  {
272    result = val[1]
273  }
274
275# 'archetype_internal_ref' is a node that refers to a previously defined object node in the same archetype.
276archetype_internal_ref: SYM_USE_NODE type_identifier c_occurrences absolute_path
277  {
278    result = {:type_identifier => val[1], :c_occurrences => val[2], :absolute_path => val[3] }
279  }
280  | SYM_USE_NODE type_identifier error
281
282# 'archetype_slot' is a node whose statements define a constraint that determines which other archetypes may appear at that point in the current archetype.
283archetype_slot: c_archetype_slot_head SYM_MATCHES SYM_START_CBLOCK c_includes c_excludes SYM_END_CBLOCK
284  {
285    result = OpenEHR::AM::Archetype::Constraint_Model::ARCHETYPE_SLOT.create do |archetype_slot|
286      archetype_slot.includes = val[3]
287      archetype_slot.excludes = val[4]
288      archetype_slot.rm_type_name = val[0][:c_archetype_slot_id]
289      archetype_slot.occurrences = val[0][:c_occurrences]
290    end
291  }
292c_archetype_slot_head: c_archetype_slot_id c_occurrences
293  {
294    result = {:c_archetype_slot_id => val[0],:c_occurrences => val[1]}
295  }
296
297c_archetype_slot_id: SYM_ALLOW_ARCHETYPE type_identifier
298  {
299    result = val[1]
300  }
301  | SYM_ALLOW_ARCHETYPE type_identifier V_LOCAL_TERM_CODE_REF
302  | SYM_ALLOW_ARCHETYPE error
303
304# 'c_primitive_object' is an node representing a constraint on a primitive object type.
305c_primitive_object: c_primitive
306  {
307    assert_at(__FILE__,__LINE__){val[0].kind_of?(OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_PRIMITIVE)}
308    result = OpenEHR::AM::Archetype::Constraint_Model::C_PRIMITIVE_OBJECT.create do |c_primitive_object|
309      c_primitive_object.item = val[0]
310    end
311  }
312
313c_primitive: c_integer
314  {
315    @@logger.debug("#{__FILE__}:#{__LINE__}: c_integer = #{val[0]} at #{@filename}:#{@lineno}")
316    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_INTEGER.create do |c_integer|
317      c_integer.list
318      c_integer.range
319      c_integer.assumed_value
320    end
321  }
322  | c_real
323  {
324    @@logger.debug("#{__FILE__}:#{__LINE__}: c_real = #{val[0]} at #{@filename}:#{@lineno}")
325    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_REAL.new
326  }
327  | c_date
328  {
329    @@logger.debug("#{__FILE__}:#{__LINE__}: c_date = #{val[0]} at #{@filename}:#{@lineno}")
330    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_DATE.new
331  }
332  | c_time
333  {
334    @@logger.debug("#{__FILE__}:#{__LINE__}: c_time = #{val[0]} at #{@filename}:#{@lineno}")
335    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_TIME.new
336  }
337  | c_date_time
338  {
339    @@logger.debug("#{__FILE__}:#{__LINE__}: c_date_time = #{val[0]} at #{@filename}:#{@lineno}")
340    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_DATE_TIME.new
341  }
342  | c_duration
343  {
344    @@logger.debug("#{__FILE__}:#{__LINE__}: c_duration = #{val[0]} at #{@filename}:#{@lineno}")
345    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_DURATION.new
346  }
347  | c_string
348  {
349    @@logger.debug("#{__FILE__}:#{__LINE__}: c_string = #{val[0]} at #{@filename}:#{@lineno}")
350    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_STRING.new
351  }
352  | c_boolean
353  {
354    assert_at(__FILE__,__LINE__){val[0].instance_of?(OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_BOOLEAN)}
355    @@logger.debug("#{__FILE__}:#{__LINE__}: c_boolean = #{val[0]} at #{@filename}:#{@lineno}")
356    result = val[0]
357  }
358
359c_any: Star_code
360#c_any: '*'
361
362#---------------- BODY - relationships ----------------
363
364c_attributes: c_attribute
365  {
366    result = [val[0]]
367  }
368  | c_attributes c_attribute
369  {
370    result = (val[0] << val[1])
371  }
372
373# 'c_attribute' is a node representing a constraint on an attribute in an object model.
374c_attribute: c_attr_head SYM_MATCHES SYM_START_CBLOCK c_attr_values SYM_END_CBLOCK
375  {
376    assert_at(__FILE__,__LINE__){ val[0].kind_of?(OpenEHR::AM::Archetype::Constraint_Model::C_ATTRIBUTE)}
377    c_attribute = val[0]
378    c_attribute.children = val[3]
379    result = c_attribute
380  }
381  | c_attr_head SYM_MATCHES START_REGEXP_BLOCK REGEXP_BODY END_REGEXP_BLOCK # added by akimichi
382  {
383    assert_at(__FILE__,__LINE__){ val[0].kind_of?(OpenEHR::AM::Archetype::Constraint_Model::C_ATTRIBUTE)}
384    result = val[0]
385  }
386  | c_attr_head SYM_MATCHES SYM_START_CBLOCK error SYM_END_CBLOCK
387  {
388    assert_at(__FILE__,__LINE__){ val[0].kind_of?(OpenEHR::AM::Archetype::Constraint_Model::C_ATTRIBUTE)}
389    result = val[0]
390  }
391
392
393c_attr_head: V_ATTRIBUTE_IDENTIFIER c_existence
394  {
395    @@logger.debug("#{__FILE__}:#{__LINE__}: V_ATTRIBUTE_IDENTIFIER = #{val[0]}, c_existence = #{val[1]} at #{@filename}")
396    result = OpenEHR::AM::Archetype::Constraint_Model::C_SINGLE_ATTRIBUTE.new(
397                                                                              :rm_attribute_name => val[0],
398                                                                              :existence => val[1]
399                                                                              )
400
401  }
402  | V_ATTRIBUTE_IDENTIFIER c_existence c_cardinality
403  {
404    assert_at(__FILE__,__LINE__){ val[2].instance_of?(OpenEHR::AM::Archetype::Constraint_Model::CARDINALITY) }
405    @@logger.debug("#{__FILE__}:#{__LINE__}: V_ATTRIBUTE_IDENTIFIER: #{val[0]}, c_existence = #{val[1]}, c_cardinality = #{val[2]} at #{@filename}")
406    result = OpenEHR::AM::Archetype::Constraint_Model::C_MULTIPLE_ATTRIBUTE.new(
407                                                                                :rm_attribute_name => val[0],
408                                                                                :existence => val[1],
409                                                                                :cardinality => val[2]
410                                                                                )
411  }
412
413c_attr_values: c_object
414  {
415    result = Array[val[0]]
416  }
417  | c_attr_values c_object
418  {
419    result = (val[0] << val[1])
420  }
421  | c_any # -- to allow a property to have any value
422  {
423    result = Array[val[0]]
424  }
425
426### c_includes: #-- Empty
427###     | SYM_INCLUDE assertions
428c_includes: #-- Empty
429    | SYM_INCLUDE invariants
430{
431    result = val[1]
432}
433
434### c_excludes: #-- Empty
435###     | SYM_EXCLUDE assertions
436c_excludes: #-- Empty
437    | SYM_EXCLUDE invariants
438{
439    result = val[1]
440}
441
442invariants: invariant
443  | invariants invariant
444
445invariant: any_identifier ':' boolean_expression
446  | boolean_expression
447  | any_identifier ':' error
448
449arch_invariant: #-- no invariant ok
450    | SYM_INVARIANT V_ASSERTION_TEXT
451    | SYM_INVARIANT error
452
453# define all linguistic entries in this part as dADL.
454#arch_ontology: SYM_ONTOLOGY V_DADL_TEXT
455#  | SYM_ONTOLOGY error
456
457arch_ontology: SYM_ONTOLOGY dadl_section
458  {
459    dadl_section = val[1]
460    result = OpenEHR::AM::Archetype::Ontology::ARCHETYPE_ONTOLOGY.new
461  }
462  | SYM_ONTOLOGY error
463
464
465### dADL section
466dadl_section: dadl_input
467
468dadl_input: attr_vals
469  | complex_object_block
470#  | error
471
472attr_vals: attr_val
473  {
474    result = Array[val[0]]
475  }
476  | attr_vals attr_val
477  {
478    result = (val[0] << val[1])
479  }
480  | attr_vals Semicolon_code attr_val
481  {
482    result = (val[0] << val[2])
483  }
484
485attr_val: attr_id SYM_EQ object_block
486  {
487    @@logger.debug("#{__FILE__}:#{__LINE__}: attr_id = #{val[0]} at #{@filename}:#{@lineno}")
488    result = {:attr_id => val[0], :object_block => val[2]}
489  }
490
491attr_id: V_ATTRIBUTE_IDENTIFIER
492  {
493    @@logger.debug("#{__FILE__}:#{__LINE__}: V_ATTRIBUTE_IDENTIFIER = #{val[0]} at #{@filename}:#{@lineno}")
494    result = val[0]
495  }
496  | V_ATTRIBUTE_IDENTIFIER error
497
498object_block: complex_object_block
499  {
500    result = val[0]
501  }
502  | primitive_object_block
503  {
504    result = val[0]
505  }
506
507complex_object_block: single_attr_object_block
508  {
509    result = val[0]
510  }
511  | multiple_attr_object_block
512  {
513    result = val[0]
514  }
515
516multiple_attr_object_block: untyped_multiple_attr_object_block
517  {
518    result = {:untyped_multiple_attr_object_block => val[0]}
519  }
520  | type_identifier untyped_multiple_attr_object_block
521  {
522    result = {:type_identifier => val[0], :untyped_multiple_attr_object_block => val[1]}
523  }
524
525untyped_multiple_attr_object_block: multiple_attr_object_block_head keyed_objects SYM_END_DBLOCK
526  {
527    result = {:multiple_attr_object_block_head => val[0], :keyed_objects => val[1]}
528  }
529
530multiple_attr_object_block_head: SYM_START_DBLOCK
531  {
532    @@logger.debug("SYM_START_DBLOCK: #{val[0]} at #{@filename}:#{@lineno}")
533    result = val[0]
534  }
535
536keyed_objects: keyed_object
537  {
538    result = Array[val[0]]
539  }
540  | keyed_objects keyed_object
541  {
542    result = (val[0] << val[1])
543  }
544
545keyed_object: object_key SYM_EQ object_block
546  {
547    @@logger.debug("#{__FILE__}:#{__LINE__}: keyed_object = #{val[0]} at #{@filename}:#{@lineno}")
548    result = {:object_key => val[0], :object_block => val[1]}
549  }
550
551object_key: Left_bracket_code simple_value Right_bracket_code
552  {
553    @@logger.debug("object_key: [#{val[1]}] at #{@filename}:#{@lineno}")
554    result = val[1]
555  }
556
557single_attr_object_block: untyped_single_attr_object_block
558  {
559    result = {:untyped_single_attr_object_block => val[0]}
560  }
561  | type_identifier untyped_single_attr_object_block
562  {
563    result = {:type_identifier => val[0], :untyped_single_attr_object_block => val[1]}
564  }
565
566untyped_single_attr_object_block: single_attr_object_complex_head SYM_END_DBLOCK # >
567  {
568    @@logger.debug("#{__FILE__}:#{__LINE__}: single_attr_object_complex_head = #{val[0]} at #{@filename}:#{@lineno}")
569    result = {:single_attr_object_complex_head => val[0]}
570  }
571  | single_attr_object_complex_head attr_vals SYM_END_DBLOCK
572  {
573    @@logger.debug("#{__FILE__}:#{__LINE__}: attr_vals = #{val[1]} at #{@filename}:#{@lineno}")
574    result = {:single_attr_object_complex_head => val[0], :attr_vals => val[1]}
575  }
576single_attr_object_complex_head: SYM_START_DBLOCK
577primitive_object_block: untyped_primitive_object_block
578  {
579    @@logger.debug("#{__FILE__}:#{__LINE__}: untyped_primitive_object_block = #{val[0]} at #{@filename}:#{@lineno}")
580    result = {:untyped_primitive_object_block => val[0]}
581  }
582  | type_identifier untyped_primitive_object_block
583  {
584    @@logger.debug("#{__FILE__}:#{__LINE__}: type_identifier = #{val[0]}, untyped_primitive_object_block = #{val[1]} at #{@filename}:#{@lineno}")
585    result = {:type_identifier => val[0], :untyped_primitive_object_block => val[1]}
586  }
587untyped_primitive_object_block: SYM_START_DBLOCK primitive_object_value SYM_END_DBLOCK
588  {
589    @@logger.debug("#{__FILE__}:#{__LINE__}: primitive_object_block = <#{val[1]}> at #{@filename}:#{@lineno}")
590    result = val[1]
591  }
592primitive_object_value: simple_value
593  {
594    result = val[0]
595  }
596  | simple_list_value
597  {
598    result = val[0]
599  }
600  | simple_interval_value
601  {
602    result = val[0]
603  }
604  | term_code
605  {
606    result = val[0]
607  }
608  | term_code_list_value
609  {
610    result = val[0]
611  }
612simple_value: string_value
613  {
614    @@logger.debug("string_value: #{val[0]} at #{@filename}:#{@lineno}")
615    result = val[0]
616  }
617  | integer_value
618  {
619    @@logger.debug("integer_value: #{val[0]} at #{@filename}:#{@lineno}")
620    result = val[0]
621  }
622  | real_value
623  {
624    @@logger.debug("real_value: #{val[0]} at #{@filename}:#{@lineno}")
625    result = val[0]
626  }
627  | boolean_value
628  {
629    @@logger.debug("boolean_value: #{val[0]} at #{@filename}:#{@lineno}")
630    result = val[0]
631  }
632  | character_value
633  {
634    @@logger.debug("character_value: #{val[0]} at #{@filename}:#{@lineno}")
635    result = val[0]
636  }
637  | date_value
638  {
639    @@logger.debug("date_value: #{val[0]} at #{@filename}:#{@lineno}")
640    result = val[0]
641  }
642  | time_value
643  {
644    @@logger.debug("time_value: #{val[0]} at #{@filename}:#{@lineno}")
645    result = val[0]
646  }
647  | date_time_value
648  {
649    @@logger.debug("date_time_value: #{val[0]} at #{@filename}:#{@lineno}")
650    result = val[0]
651  }
652  | duration_value
653  {
654    @@logger.debug("duration_value: #{val[0]} at #{@filename}:#{@lineno}")
655    result = val[0]
656  }
657  | uri_value
658  {
659    @@logger.debug("uri_value: #{val[0]} at #{@filename}:#{@lineno}")
660    result = val[0]
661  }
662
663simple_list_value: string_list_value
664  | integer_list_value
665  | real_list_value
666  | boolean_list_value
667  | character_list_value
668  | date_list_value
669  | time_list_value
670  | date_time_list_value
671  | duration_list_value
672
673simple_interval_value: integer_interval_value
674  | real_interval_value
675  | date_interval_value
676  | time_interval_value
677  | date_time_interval_value
678  | duration_interval_value
679
680type_identifier: V_TYPE_IDENTIFIER
681  {
682    @@logger.debug("V_TYPE_IDENTIFIER: #{val[0]} at #{@filename}:#{@lineno}")
683    result = val[0]
684  }
685  | V_GENERIC_TYPE_IDENTIFIER
686  {
687    @@logger.debug("V_GENERIC_TYPE_IDENTIFIER: #{val[0]} at #{@filename}:#{@lineno}")
688    result = val[0]
689  }
690
691string_value: V_STRING
692  {
693    @@logger.debug("V_STRING: #{val[0]} at #{@filename}:#{@lineno}")
694    result = val[0]
695  }
696
697string_list_value: V_STRING Comma_code V_STRING
698  | string_list_value Comma_code V_STRING
699  | V_STRING Comma_code SYM_LIST_CONTINUE
700
701integer_value: V_INTEGER
702  {
703    begin
704      integer = Integer(val[0])
705    rescue
706      raise
707    end
708    result = integer
709  }
710  | Plus_code V_INTEGER
711  {
712    begin
713      integer = Integer(val[0])
714    rescue
715      raise
716    end
717    result = integer
718  }
719  | Minus_code V_INTEGER
720  {
721    begin
722      integer = Integer(val[0])
723    rescue
724      raise
725    end
726    result = - integer
727  }
728###   | '+' V_INTEGER
729###   | '-' V_INTEGER
730
731integer_list_value: integer_value Comma_code integer_value
732  | integer_list_value Comma_code integer_value
733  | integer_value Comma_code SYM_LIST_CONTINUE
734
735integer_interval_value: SYM_INTERVAL_DELIM integer_value SYM_ELLIPSIS integer_value SYM_INTERVAL_DELIM
736  | SYM_INTERVAL_DELIM SYM_GT integer_value SYM_ELLIPSIS integer_value SYM_INTERVAL_DELIM
737  | SYM_INTERVAL_DELIM integer_value SYM_ELLIPSIS SYM_LT integer_value SYM_INTERVAL_DELIM
738  | SYM_INTERVAL_DELIM SYM_GT integer_value SYM_ELLIPSIS SYM_LT integer_value SYM_INTERVAL_DELIM
739  | SYM_INTERVAL_DELIM SYM_LT integer_value SYM_INTERVAL_DELIM
740  | SYM_INTERVAL_DELIM SYM_LE integer_value SYM_INTERVAL_DELIM
741  | SYM_INTERVAL_DELIM SYM_GT integer_value SYM_INTERVAL_DELIM
742  | SYM_INTERVAL_DELIM SYM_GE integer_value SYM_INTERVAL_DELIM
743  | SYM_INTERVAL_DELIM integer_value SYM_INTERVAL_DELIM
744
745real_value: V_REAL
746  {
747    begin
748      real = Float(val[0])
749    rescue
750      raise
751    end
752    result = real
753  }
754  | Plus_code V_REAL
755  {
756    begin
757      real = Float(val[1])
758    rescue
759      raise
760    end
761    result = real
762  }
763  | Minus_code V_REAL
764  {
765    begin
766      real = Float(val[1])
767    rescue
768      raise
769    end
770    result = - real
771  }
772
773real_list_value: real_value Comma_code real_value
774  | real_list_value Comma_code real_value
775  | real_value Comma_code SYM_LIST_CONTINUE
776
777real_interval_value: SYM_INTERVAL_DELIM real_value SYM_ELLIPSIS real_value SYM_INTERVAL_DELIM
778  | SYM_INTERVAL_DELIM SYM_GT real_value SYM_ELLIPSIS real_value SYM_INTERVAL_DELIM
779  | SYM_INTERVAL_DELIM real_value SYM_ELLIPSIS SYM_LT real_value SYM_INTERVAL_DELIM
780  | SYM_INTERVAL_DELIM SYM_GT real_value SYM_ELLIPSIS SYM_LT real_value SYM_INTERVAL_DELIM
781  | SYM_INTERVAL_DELIM SYM_LT real_value SYM_INTERVAL_DELIM
782  | SYM_INTERVAL_DELIM SYM_LE real_value SYM_INTERVAL_DELIM
783  | SYM_INTERVAL_DELIM SYM_GT real_value SYM_INTERVAL_DELIM
784  | SYM_INTERVAL_DELIM SYM_GE real_value SYM_INTERVAL_DELIM
785  | SYM_INTERVAL_DELIM real_value SYM_INTERVAL_DELIM
786
787
788boolean_value: SYM_TRUE
789  {
790    result = true
791  }
792  | SYM_FALSE
793  {
794    result = false
795  }
796
797boolean_list_value: boolean_value Comma_code boolean_value
798  | boolean_list_value Comma_code boolean_value
799  | boolean_value Comma_code SYM_LIST_CONTINUE
800
801character_value: V_CHARACTER
802
803character_list_value: character_value Comma_code character_value
804  | character_list_value Comma_code character_value
805  | character_value Comma_code SYM_LIST_CONTINUE
806
807date_value: V_ISO8601_EXTENDED_DATE
808
809date_list_value: date_value Comma_code date_value
810  | date_list_value Comma_code date_value
811  | date_value Comma_code SYM_LIST_CONTINUE
812
813date_interval_value: SYM_INTERVAL_DELIM date_value SYM_ELLIPSIS date_value SYM_INTERVAL_DELIM
814  | SYM_INTERVAL_DELIM SYM_GT date_value SYM_ELLIPSIS date_value SYM_INTERVAL_DELIM
815  | SYM_INTERVAL_DELIM date_value SYM_ELLIPSIS SYM_LT date_value SYM_INTERVAL_DELIM
816  | SYM_INTERVAL_DELIM SYM_GT date_value SYM_ELLIPSIS SYM_LT date_value SYM_INTERVAL_DELIM
817  | SYM_INTERVAL_DELIM SYM_LT date_value SYM_INTERVAL_DELIM
818  | SYM_INTERVAL_DELIM SYM_LE date_value SYM_INTERVAL_DELIM
819  | SYM_INTERVAL_DELIM SYM_GT date_value SYM_INTERVAL_DELIM
820  | SYM_INTERVAL_DELIM SYM_GE date_value SYM_INTERVAL_DELIM
821  | SYM_INTERVAL_DELIM date_value SYM_INTERVAL_DELIM
822
823time_value: V_ISO8601_EXTENDED_TIME
824
825time_list_value: time_value Comma_code time_value
826  | time_list_value Comma_code time_value
827  | time_value Comma_code SYM_LIST_CONTINUE
828
829time_interval_value: SYM_INTERVAL_DELIM time_value SYM_ELLIPSIS time_value SYM_INTERVAL_DELIM
830  | SYM_INTERVAL_DELIM SYM_GT time_value SYM_ELLIPSIS time_value SYM_INTERVAL_DELIM
831  | SYM_INTERVAL_DELIM time_value SYM_ELLIPSIS SYM_LT time_value SYM_INTERVAL_DELIM
832  | SYM_INTERVAL_DELIM SYM_GT time_value SYM_ELLIPSIS SYM_LT time_value SYM_INTERVAL_DELIM
833  | SYM_INTERVAL_DELIM SYM_LT time_value SYM_INTERVAL_DELIM
834  | SYM_INTERVAL_DELIM SYM_LE time_value SYM_INTERVAL_DELIM
835  | SYM_INTERVAL_DELIM SYM_GT time_value SYM_INTERVAL_DELIM
836  | SYM_INTERVAL_DELIM SYM_GE time_value SYM_INTERVAL_DELIM
837  | SYM_INTERVAL_DELIM time_value SYM_INTERVAL_DELIM
838
839date_time_value: V_ISO8601_EXTENDED_DATE_TIME
840
841date_time_list_value: date_time_value Comma_code date_time_value
842  | date_time_list_value Comma_code date_time_value
843  | date_time_value Comma_code SYM_LIST_CONTINUE
844
845date_time_interval_value: SYM_INTERVAL_DELIM date_time_value SYM_ELLIPSIS date_time_value  SYM_INTERVAL_DELIM
846  | SYM_INTERVAL_DELIM SYM_GT date_time_value SYM_ELLIPSIS date_time_value SYM_INTERVAL_DELIM
847  | SYM_INTERVAL_DELIM date_time_value SYM_ELLIPSIS SYM_LT date_time_value SYM_INTERVAL_DELIM
848  | SYM_INTERVAL_DELIM SYM_GT date_time_value SYM_ELLIPSIS SYM_LT date_time_value SYM_INTERVAL_DELIM
849  | SYM_INTERVAL_DELIM SYM_LT date_time_value SYM_INTERVAL_DELIM
850  | SYM_INTERVAL_DELIM SYM_LE date_time_value SYM_INTERVAL_DELIM
851  | SYM_INTERVAL_DELIM SYM_GT date_time_value SYM_INTERVAL_DELIM
852  | SYM_INTERVAL_DELIM SYM_GE date_time_value SYM_INTERVAL_DELIM
853  | SYM_INTERVAL_DELIM date_time_value SYM_INTERVAL_DELIM
854
855duration_value: V_ISO8601_DURATION
856  {
857    @@logger.debug("V_ISO8601_DURATION: #{val[0]} at #{@filename}:#{@lineno}")
858    result = val[0]
859  }
860
861duration_list_value: duration_value Comma_code duration_value
862  | duration_list_value Comma_code duration_value
863  | duration_value Comma_code SYM_LIST_CONTINUE
864
865duration_interval_value: SYM_INTERVAL_DELIM duration_value SYM_ELLIPSIS duration_value SYM_INTERVAL_DELIM
866  | SYM_INTERVAL_DELIM SYM_GT duration_value SYM_ELLIPSIS duration_value SYM_INTERVAL_DELIM
867  | SYM_INTERVAL_DELIM duration_value SYM_ELLIPSIS SYM_LT duration_value SYM_INTERVAL_DELIM
868  | SYM_INTERVAL_DELIM SYM_GT duration_value SYM_ELLIPSIS SYM_LT duration_value SYM_INTERVAL_DELIM
869  | SYM_INTERVAL_DELIM SYM_LT duration_value SYM_INTERVAL_DELIM
870  | SYM_INTERVAL_DELIM SYM_LE duration_value SYM_INTERVAL_DELIM
871  | SYM_INTERVAL_DELIM SYM_GT duration_value SYM_INTERVAL_DELIM
872  | SYM_INTERVAL_DELIM SYM_GE duration_value SYM_INTERVAL_DELIM
873  | SYM_INTERVAL_DELIM duration_value SYM_INTERVAL_DELIM
874
875term_code: V_QUALIFIED_TERM_CODE_REF
876  {
877    @@logger.debug("#{__FILE__}:#{__LINE__}: V_QUALIFIED_TERM_CODE_REF = #{val[0]} at #{@filename}:#{@lineno}")
878    result = val[0]
879  }
880
881term_code_list_value: term_code Comma_code term_code
882  | term_code_list_value Comma_code term_code
883  | term_code Comma_code SYM_LIST_CONTINUE
884
885uri_value: V_URI
886  {
887    @@logger.debug("#{__FILE__}:#{__LINE__}: V_URI = #{val[0]} at #{@filename}:#{@lineno}")
888    result = val[0]
889  }
890
891
892#---------------------- ASSERTIONS ------------------------
893
894assertions: assertion
895  | assertions assertion
896
897assertion: any_identifier ':' boolean_expression
898  | boolean_expression
899  | any_identifier ':' error
900
901#---------------------- expressions ---------------------
902
903boolean_expression: boolean_leaf
904  | boolean_node
905
906boolean_node: SYM_EXISTS absolute_path
907#  | absolute_path
908  | SYM_EXISTS error
909  | relative_path SYM_MATCHES SYM_START_CBLOCK c_primitive SYM_END_CBLOCK
910  | relative_path SYM_MATCHES START_REGEXP_BLOCK REGEXP_BODY END_REGEXP_BLOCK # added by akimichi
911  | SYM_NOT boolean_leaf
912  | arithmetic_expression '=' arithmetic_expression
913  | arithmetic_expression SYM_NE arithmetic_expression
914  | arithmetic_expression SYM_LT arithmetic_expression
915  | arithmetic_expression SYM_GT arithmetic_expression
916  | arithmetic_expression SYM_LE arithmetic_expression
917  | arithmetic_expression SYM_GE arithmetic_expression
918  | boolean_expression SYM_AND boolean_expression
919  | boolean_expression SYM_OR boolean_expression
920  | boolean_expression SYM_XOR boolean_expression
921  | boolean_expression SYM_IMPLIES boolean_expression
922
923boolean_leaf: Left_parenthesis_code boolean_expression Right_parenthesis_code
924  | SYM_TRUE
925  | SYM_FALSE
926
927arithmetic_expression: arithmetic_leaf
928  | arithmetic_node
929
930arithmetic_node: arithmetic_expression '+' arithmetic_leaf
931  | arithmetic_expression '-' arithmetic_leaf
932  | arithmetic_expression Star_code arithmetic_leaf
933  | arithmetic_expression Slash_code arithmetic_leaf
934  | arithmetic_expression '^' arithmetic_leaf
935
936arithmetic_leaf:  Left_parenthesis_code arithmetic_expression Right_parenthesis_code
937  | integer_value
938  | real_value
939  | absolute_path
940
941
942#--------------- THE FOLLOWING SOURCE TAKEN FROM OG_PATH_VALIDATOR.Y -------------
943#--------------- except to remove movable_path ----------------------------------------------------
944
945
946absolute_path: Slash_code
947  | Slash_code relative_path
948#  | absolute_path Slash_code relative_path
949
950
951
952relative_path: path_segment
953  | relative_path Slash_code path_segment
954
955path_segment: V_ATTRIBUTE_IDENTIFIER V_LOCAL_TERM_CODE_REF
956  {
957    @@logger.debug("#{__FILE__}:#{__LINE__}, V_ATTRIBUTE_IDENTIFIER = #{val[0]} at #{@filename}")
958  }
959  | V_ATTRIBUTE_IDENTIFIER
960  {
961    @@logger.debug("#{__FILE__}:#{__LINE__}, V_ATTRIBUTE_IDENTIFIER = #{val[0]} at #{@filename}")
962  }
963
964
965#-------------------------------- END SOURCE TAKEN FROM OG_PATH_VALIDATOR.Y ----------------------
966
967
968#---------------- existence, occurrences, cardinality ----------------
969
970c_existence: #-- default to 1..1
971    {
972    result = Range.new(1,1)
973  }
974  | SYM_EXISTENCE SYM_MATCHES SYM_START_CBLOCK existence_spec SYM_END_CBLOCK
975  {
976    result = val[3]
977  }
978
979existence_spec:  V_INTEGER #-- can only be 0 or 1
980  {
981    begin
982      integer = Integer(val[0])
983    rescue
984      raise
985    end
986    result = integer
987  }
988  | V_INTEGER SYM_ELLIPSIS V_INTEGER #-- can only be 0..0, 0..1, 1..1
989  {
990    begin
991      from_integer = Integer(val[0])
992      to_integer = Integer(val[2])
993    rescue
994      raise
995    end
996    result = Range.new(from_integer,to_integer)
997  }
998
999c_cardinality: SYM_CARDINALITY SYM_MATCHES SYM_START_CBLOCK cardinality_spec SYM_END_CBLOCK
1000  {
1001    result = OpenEHR::AM::Archetype::Constraint_Model::CARDINALITY.new
1002  }
1003
1004cardinality_spec: occurrence_spec
1005  | occurrence_spec Semicolon_code SYM_ORDERED
1006  | occurrence_spec Semicolon_code SYM_UNORDERED
1007  | occurrence_spec Semicolon_code SYM_UNIQUE
1008  | occurrence_spec Semicolon_code SYM_ORDERED Semicolon_code SYM_UNIQUE
1009  | occurrence_spec Semicolon_code SYM_UNORDERED Semicolon_code SYM_UNIQUE
1010  | occurrence_spec Semicolon_code SYM_UNIQUE Semicolon_code SYM_ORDERED
1011  | occurrence_spec Semicolon_code SYM_UNIQUE Semicolon_code SYM_UNORDERED
1012
1013cardinality_limit_value: integer_value
1014  {
1015    result = val[0]
1016  }
1017  | Star_code # '*'
1018  {
1019    result = val[0]
1020  }
1021
1022
1023c_occurrences:  #-- default to 1..1
1024  | SYM_OCCURRENCES SYM_MATCHES SYM_START_CBLOCK occurrence_spec SYM_END_CBLOCK
1025  {
1026    result = val[3]
1027  }
1028  | SYM_OCCURRENCES error
1029
1030occurrence_spec: cardinality_limit_value #-- single integer or '*'
1031  | V_INTEGER SYM_ELLIPSIS cardinality_limit_value
1032
1033#---------------------- leaf constraint types -----------------------
1034
1035c_integer_spec: integer_value
1036  | integer_list_value
1037  | integer_interval_value
1038
1039c_integer: c_integer_spec
1040  | c_integer_spec Semicolon_code integer_value
1041  | c_integer_spec Semicolon_code error
1042
1043c_real_spec: real_value
1044  | real_list_value
1045  | real_interval_value
1046
1047c_real: c_real_spec
1048  | c_real_spec Semicolon_code real_value
1049  | c_real_spec Semicolon_code error
1050
1051c_date_constraint: V_ISO8601_DATE_CONSTRAINT_PATTERN
1052  | date_value
1053  | date_interval_value
1054
1055c_date: c_date_constraint
1056  | c_date_constraint Semicolon_code date_value
1057  | c_date_constraint Semicolon_code error
1058
1059c_time_constraint: V_ISO8601_TIME_CONSTRAINT_PATTERN
1060  | time_value
1061  | time_interval_value
1062
1063c_time: c_time_constraint
1064  | c_time_constraint Semicolon_code time_value
1065  | c_time_constraint Semicolon_code error
1066
1067c_date_time_constraint: V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN
1068  | date_time_value
1069  | date_time_interval_value
1070
1071c_date_time: c_date_time_constraint
1072  | c_date_time_constraint Semicolon_code date_time_value
1073  | c_date_time_constraint Semicolon_code error
1074
1075c_duration_constraint: duration_pattern
1076  | duration_pattern Slash_code duration_interval_value
1077  | duration_value
1078  | duration_interval_value
1079
1080c_duration: c_duration_constraint
1081  | c_duration_constraint Semicolon_code duration_value
1082  | c_duration_constraint Semicolon_code error
1083
1084c_string_spec:  V_STRING #-- single value, generates closed list
1085  | string_list_value #-- closed list
1086  | string_list_value Comma_code SYM_LIST_CONTINUE #-- open list
1087#  | string_list_value ',' SYM_LIST_CONTINUE #-- open list
1088#  | V_REGEXP #-- regular expression with "//" or "^^" delimiters
1089
1090c_string: c_string_spec
1091  | c_string_spec Semicolon_code string_value
1092  | c_string_spec Semicolon_code error
1093
1094c_boolean_spec: SYM_TRUE
1095  {
1096    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_BOOLEAN.new(:true_valid => true)
1097  }
1098  | SYM_FALSE
1099  {
1100    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_BOOLEAN.new(:true_valid => false)
1101  }
1102  | SYM_TRUE Comma_code SYM_FALSE
1103  {
1104    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_BOOLEAN.new(:true_valid => true,:false_valid => false)
1105  }
1106  | SYM_FALSE Comma_code SYM_TRUE
1107  {
1108    result = OpenEHR::AM::Archetype::Constraint_Model::Primitive::C_BOOLEAN.new(:true_valid => false,:false_valid => true)
1109  }
1110
1111c_boolean: c_boolean_spec
1112  {
1113    result = val[0]
1114  }
1115  | c_boolean_spec Semicolon_code boolean_value
1116  {
1117    raise 'Not implemented yet'
1118  }
1119  | c_boolean_spec Semicolon_code error
1120  {
1121    raise 'Not implemented yet'
1122  }
1123
1124c_ordinal: c_ordinal_spec
1125  | c_ordinal_spec Semicolon_code integer_value
1126  | c_ordinal_spec Semicolon_code error
1127
1128c_ordinal_spec: ordinal
1129  | c_ordinal_spec Comma_code ordinal
1130
1131ordinal: integer_value SYM_INTERVAL_DELIM V_QUALIFIED_TERM_CODE_REF
1132  {
1133    @in_interval = false
1134    @@logger.debug("#{__FILE__}:#{__LINE__}, #{val[0]}|#{val[2]} at #{@filename}")
1135  }
1136
1137#c_code_phrase: V_TERM_CODE_CONSTRAINT #-- e.g. "[local::at0040, at0041; at0040]"
1138c_code_phrase: term_code_constraint_section #-- e.g. "[local::at0040, at0041; at0040]"
1139  {
1140      result = val[0]
1141  }
1142  | V_QUALIFIED_TERM_CODE_REF
1143  {
1144      result = val[0]
1145  }
1146
1147#                             [[a-zA-Z0-9\(\)\._\-]+::[ \t\n]*          [[a-zA-Z0-9\._\-]*[ \t]*]
1148term_code_constraint_section: START_TERM_CODE_CONSTRAINT term_code_body END_TERM_CODE_CONSTRAINT
1149  {
1150    @@logger.debug("#{__FILE__}:#{__LINE__}, START_TERM_CODE_CONSTRAINT = #{val[0]} at #{@filename}")
1151    @@logger.debug("#{__FILE__}:#{__LINE__}, term_code_body = #{val[1]}")
1152    @@logger.debug("#{__FILE__}:#{__LINE__}, END_TERM_CODE_CONSTRAINT = #{val[2]}")
1153    result = val[1]
1154  }
1155
1156
1157term_code_body: # empty
1158  | TERM_CODE
1159  | term_code_body TERM_CODE
1160### term_code_body: TERM_CODE
1161###   | term_code_body TERM_CODE
1162
1163# A Constraint_Ref is a proxy for a set of constraints on an object.
1164constraint_ref: V_LOCAL_TERM_CODE_REF #-- e.g. "ac0003"
1165  {
1166      result = val[0]
1167  }
1168
1169any_identifier: type_identifier
1170  {
1171      result = val[0]
1172  }
1173  | V_ATTRIBUTE_IDENTIFIER
1174  {
1175    @@logger.debug("#{__FILE__}:#{__LINE__}, V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}")
1176      result = val[0]
1177  }
1178
1179
1180#----------------- TAKEN FROM DADL_VALIDATOR.Y -------------------
1181#-----------------        DO NOT MODIFY        -------------------
1182#---------------------- BASIC DATA VALUES -----------------------
1183
1184duration_pattern: V_ISO8601_DURATION_CONSTRAINT_PATTERN
1185  {
1186    result = val[0]
1187  }
1188
1189
1190
1191---- header
1192
1193
1194$:.unshift File.join(File.dirname(__FILE__))
1195require 'logger'
1196require 'rubygems'
1197require 'adl_parser.rb'
1198require 'am.rb'
1199require 'rm.rb'
1200$DEBUG = true
1201
1202
1203
1204---- inner
1205
1206def assert_at(file,line, message = "")
1207  unless yield
1208    raise "Assertion failed !: #{file}, #{line}: #{message}"
1209  end
1210end
1211
1212if $DEBUG
1213  @@logger = Logger.new('log/parser.log','daily')
1214  @@logger.level = Logger::DEBUG
1215else
1216  @@logger = Logger.new(STDOUT)
1217  @@logger.level = Logger::WARN
1218end
1219
1220@@dadl_scanner = OpenEHR::ADL::Scanner::DADL::RootScanner.new
1221@@cadl_scanner = OpenEHR::ADL::Scanner::CADL::RootScanner.new
1222
1223###----------/* keywords */ ---------------------------------------------
1224@@adl_reserved = {
1225    'archetype' => :SYM_ARCHETYPE,
1226    'adl_version' => :SYM_ADL_VERSION,
1227    'controlled' => :SYM_IS_CONTROLLED,
1228    'specialize' => :SYM_SPECIALIZE,
1229    'concept' => :SYM_CONCEPT,
1230    'language' => :SYM_LANGUAGE,
1231    'description' => :SYM_DESCRIPTION,
1232    'definition' => :SYM_DEFINITION,
1233    'invariant' => :SYM_INVARIANT,
1234    'ontology' => :SYM_ONTOLOGY,
1235    'matches' => :SYM_MATCHES,
1236    'is_in' => :SYM_MATCHES,
1237    'occurrences' => :SYM_OCCURRENCES,
1238    'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1239    'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1240    'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1241}
1242
1243@@dadl_reserved = {
1244  'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1245  'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1246  'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1247}
1248
1249@@cadl_reserved = {
1250  'then' => :SYM_THEN, # [Tt][Hh][Ee][Nn]
1251  'else' => :SYM_ELSE, # [Ee][Ll][Ss][Ee]
1252  'and' => :SYM_AND, # [Aa][Nn][Dd]
1253  'or' => :SYM_OR, # [Oo][Rr]
1254  'xor' => :SYM_XOR, # [Xx][Oo][Rr]
1255  'not' => :SYM_NOT, # [Nn][Oo][Tt]
1256  'implies' => :SYM_IMPLIES, # [Ii][Mm][Pp][Ll][Ii][Ee][Ss]
1257  'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1258  'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1259  'forall' => :SYM_FORALL, # [Ff][Oo][Rr][_][Aa][Ll][Ll]
1260  'exists' => :SYM_EXISTS, # [Ee][Xx][Ii][Ss][Tt][Ss]
1261  'existence' => :SYM_EXISTENCE, # [Ee][Xx][Iu][Ss][Tt][Ee][Nn][Cc][Ee]
1262  'occurrences' => :SYM_OCCURRENCES, # [Oo][Cc][Cc][Uu][Rr][Rr][Ee][Nn][Cc][Ee][Ss]
1263  'cardinality' => :SYM_CARDINALITY, # [Cc][Aa][Rr][Dd][Ii][Nn][Aa][Ll][Ii][Tt][Yy]
1264  'ordered' => :SYM_ORDERED, # [Oo][Rr][Dd][Ee][Rr][Ee][Dd]
1265  'unordered' => :SYM_UNORDERED, # [Uu][Nn][Oo][Rr][Dd][Ee][Rr][Ee][Dd]
1266  'unique' => :SYM_UNIQUE, # [Uu][Nn][Ii][Qq][Uu][Ee]
1267  'matches' => :SYM_MATCHES, # [Mm][Aa][Tt][Cc][Hh][Ee][Ss]
1268  'is_in' => :SYM_MATCHES, # [Ii][Ss][_][Ii][Nn]
1269  'invariant' => :SYM_INVARIANT, # [Ii][Nn][Vv][Aa][Rr][Ii][Aa][Nn][Tt]
1270  'infinity' => :SYM_INFINITY, # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1271  'use_node' => :SYM_USE_NODE, # [Uu][Ss][Ee][_][Nn][Oo][Dd][Ee]
1272  'use_archetype' => :SYM_ALLOW_ARCHETYPE, # [Uu][Ss][Ee][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
1273  'allow_archetype' => :SYM_ALLOW_ARCHETYPE, # [Aa][Ll][Ll][Oo][Ww][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
1274  'include' => :SYM_INCLUDE, # [Ii][Nn][Cc][Ll][Uu][Dd][Ee]
1275  'exclude' => :SYM_EXCLUDE # [Ee][Xx][Cc][Ll][Uu][Dd][Ee]
1276}
1277
1278
1279###----------/* Scanner */ -----------------------------------------------
1280
1281
1282def scan
1283  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan at #{@filename}:#{@lineno}:")
1284  adl_scanner = OpenEHR::ADL::Scanner::ADLScanner.new(@adl_type, @filename)
1285  cadl_scanner = OpenEHR::ADL::Scanner::CADLScanner.new(@adl_type, @filename)
1286  dadl_scanner = OpenEHR::ADL::Scanner::DADLScanner.new(@adl_type, @filename)
1287  regex_scanner = OpenEHR::ADL::Scanner::RegexScanner.new(@adl_type, @filename)
1288  term_constraint_scanner = OpenEHR::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename)
1289
1290  until @data.nil?  do
1291    case @adl_type.last
1292    when :adl
1293      @data = adl_scanner.scan(@data) do |sym, val|
1294        yield sym, val
1295      end
1296    when :dadl
1297      @data = dadl_scanner.scan(@data) do |sym, val|
1298        yield sym, val
1299      end
1300    when :cadl
1301      @data = cadl_scanner.scan(@data) do |sym, val|
1302        yield sym, val
1303      end
1304    when :regexp
1305      @data = regex_scanner.scan(@data) do |sym, val|
1306        yield sym, val
1307      end
1308    when :term_constraint
1309      @@logger.debug("#{__FILE__}:#{__LINE__}: scan: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{@data.inspect}")
1310      @data = term_constraint_scanner.scan(@data) do |sym, val|
1311        yield sym, val
1312      end
1313    else
1314      raise
1315    end
1316    @data = $' # variable $' receives the string after the match
1317  end
1318  yield :EOF, nil
1319  yield false, '$'
1320end # of scan
1321
1322### def scan
1323###   @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan at #{@filename}:#{@lineno}:")
1324 
1325###   until @data.nil?  do
1326###     case @adl_type.last
1327###     when :adl
1328###       @data = scan_adl(@data) do |sym, val|
1329###         yield sym, val
1330###       end
1331###     when :dadl
1332###       @data = scan_dadl(@data) do |sym, val|
1333###         yield sym, val
1334###       end
1335###     when :cadl
1336###       @data = scan_cadl(@data) do |sym, val|
1337###         yield sym, val
1338###       end
1339###     when :regexp
1340###       @data = scan_regexp(@data) do |sym, val|
1341###         yield sym, val
1342###       end
1343###     when :term_constraint
1344###       @@logger.debug("#{__FILE__}:#{__LINE__}: scan: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1345###       @data = scan_term_constraint(@data) do |sym, val|
1346###         yield sym, val
1347###       end
1348###     else
1349###       raise
1350###     end
1351###     @data = $' # variable $' receives the string after the match
1352###   end
1353###   yield :EOF, nil
1354###   yield false, '$'
1355### end # of scan
1356
1357def scan_adl(data)
1358  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_adl at #{@filename}:#{@lineno}: data = #{data.inspect}")
1359  until data.nil?  do
1360    case @adl_type.last
1361    when :adl
1362      case data
1363      when /\A\n/ # carriage return
1364        @lineno += 1
1365        ;
1366      when /\A[ \t\r\f]+/ #just drop it
1367        ;
1368      when /\A--.*\n/ # single line comment
1369        @lineno += 1
1370        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1371        ;
1372      when /\Adescription/   # description
1373        yield :SYM_DESCRIPTION, :SYM_DESCRIPTION
1374      when /\Adefinition/   # definition
1375        yield :SYM_DEFINITION, :SYM_DEFINITION
1376        ###----------/* symbols */ -------------------------------------------------
1377      when /\A[A-Z][a-zA-Z0-9_]*/
1378        yield :V_TYPE_IDENTIFIER, $&
1379#      when /\A[a-zA-Z][a-zA-Z0-9_-]+\.[a-zA-Z][a-zA-Z0-9_-]+\.[a-zA-Z0-9]+/   #V_ARCHETYPE_ID
1380      when /\A(\w+)-(\w+)-(\w+)\.(\w+)(-\w+)?\.(v\w+)/   #V_ARCHETYPE_ID
1381        object_id, rm_originator, rm_name, rm_entity, concept_name, specialisation, version_id = $&, $1, $2, $3, $4, $5, $6
1382        archetype_id = OpenEHR::RM::Support::Identification::Archetype_ID.new(object_id, concept_name, rm_name, rm_entity, rm_originator, specialisation, version_id)
1383#        yield :V_ARCHETYPE_ID, $&
1384        yield :V_ARCHETYPE_ID, archetype_id
1385      when /\A[a-z][a-zA-Z0-9_]*/
1386#        word = $&.downcase
1387        word = $&
1388        if @@adl_reserved[word]
1389          @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: @@adl_reserved = #{@@adl_reserved[word]} at #{@filename}:#{@lineno}")
1390          yield @@adl_reserved[word], @@adl_reserved[word]
1391        elsif #/\A[A-Z][a-zA-Z0-9_]*/
1392          @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: V_ATTRIBUTE_IDENTIFIER = #{$&} at #{@filename}:#{@lineno}")
1393          yield :V_ATTRIBUTE_IDENTIFIER, $&
1394        end
1395      when /\A\=/   # =
1396        yield :SYM_EQ, :SYM_EQ
1397      when /\A\>=/   # >=
1398        yield :SYM_GE, :SYM_GE
1399      when /\A\<=/   # <=
1400        yield :SYM_LE, :SYM_LE
1401      when /\A\</   # <
1402        if @in_interval
1403#          @start_block_received = false
1404          yield :SYM_LT, :SYM_LT
1405        else
1406#          @start_block_received = true
1407          @adl_type.push(:dadl)
1408          yield :SYM_START_DBLOCK,  $&
1409        end
1410      when /\A\>/   # >
1411        if @in_interval
1412          yield :SYM_GT, :SYM_GT
1413        else
1414          adl_type = @adl_type.pop
1415          assert_at(__FILE__,__LINE__){adl_type == :dadl}
1416          yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
1417        end
1418      when /\A\{/   # {
1419        @adl_type.push(:cadl)
1420        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: entering cADL at #{@filename}:#{@lineno}")
1421        yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
1422      when /\A\}/   # }
1423        adl_type = @adl_type.pop
1424#        puts "Escaping #{adl_type}"
1425        assert_at(__FILE__,__LINE__){adl_type == :cadl}
1426        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: exiting cADL at #{@filename}:#{@lineno}")
1427        yield :SYM_END_CBLOCK, $&
1428      when /\A\-/   # -
1429        yield :Minus_code, :Minus_code
1430      when /\A\+/   # +
1431        yield :Plus_code, :Plus_code
1432      when /\A\*/   # *
1433        yield :Star_code, :Star_code
1434      when /\A\//   # /
1435        yield :Slash_code, :Slash_code
1436      when /\A\^/   # ^
1437        yield :Caret_code, :Caret_code
1438      when /\A\=/   # =
1439        yield :Equal_code, :Equal_code
1440      when /\A\.\.\./   # ...
1441        yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
1442      when /\A\.\./   # ..
1443        yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
1444      when /\A\./   # .
1445        yield :Dot_code, :Dot_code
1446      when /\A\;/   # ;
1447        yield :Semicolon_code, :Semicolon_code
1448      when /\A\,/   # ,
1449        yield :Comma_code, :Comma_code
1450      when /\A\:/   # :
1451        yield :Colon_code, :Colon_code
1452      when /\A\!/   # !
1453        yield :Exclamation_code, :Exclamation_code
1454      when /\A\(/   # (
1455        yield :Left_parenthesis_code, :Left_parenthesis_code
1456      when /\A\)/   # )
1457        yield :Right_parenthesis_code, :Right_parenthesis_code
1458      when /\A\$/   # $
1459        yield :Dollar_code, :Dollar_code
1460      when /\A\?\?/   # ??
1461        yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
1462      when /\A\?/   # ?
1463        yield :Question_mark_code, :Question_mark_code
1464      when /\A[0-9]+\.[0-9]+(\.[0-9]+)*/   # ?
1465        yield :V_VERSION_STRING, $&
1466      when /\A\|/   # |
1467        if @in_interval
1468          @in_interval = false
1469        else
1470          @in_interval = true
1471        end
1472        yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
1473      when /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/
1474#      when /\A\[[a-zA-Z0-9()\._-]+\:\:[a-zA-Z0-9\._-]+\]/   #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1475        yield :V_QUALIFIED_TERM_CODE_REF, $&
1476      when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
1477        yield :V_LOCAL_TERM_CODE_REF, $&
1478      when /\A\[/   # [
1479        yield :Left_bracket_code, :Left_bracket_code
1480      when /\A\]/   # ]
1481        yield :Right_bracket_code, :Right_bracket_code
1482
1483      when /\A"([^"]*)"/m #V_STRING
1484        yield :V_STRING, $1
1485      when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
1486        yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
1487      when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
1488        yield :V_LOCAL_CODE, $&
1489      when /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](,[0-9]+)?(Z|[+-][0-9]{4})?|[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9](Z|[+-][0-9]{4})?|[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9](Z|[+-][0-9]{4})?/   #V_ISO8601_EXTENDED_DATE_TIME YYYY-MM-DDThh:mm:ss[,sss][Z|+/- -n-n-n-n-]-
1490        yield :V_ISO8601_EXTENDED_DATE_TIME, $&
1491      when /\A[0-2][0-9]:[0-6][0-9]:[0-6][0-9](,[0-9]+)?(Z|[+-][0-9]{4})?|[0-2][0-9]:[0-6][0-9](Z|[+-][0-9]{4})? /   #V_ISO8601_EXTENDED_TIME hh:mm:ss[,sss][Z|+/-nnnn]
1492        yield :V_ISO8601_EXTENDED_TIME, $&
1493      when /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]|[0-9]{4}-[0-1][0-9]/   #V_ISO8601_EXTENDED_DATE YYYY-MM-DD
1494        yield :V_ISO8601_EXTENDED_DATE, $&
1495      when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1496        yield :V_GENERIC_TYPE_IDENTIFIER, $&
1497      when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
1498        yield :V_INTEGER, $&
1499      when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
1500        yield :V_REAL, $&
1501        #    when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
1502      when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
1503        yield :V_URI, $&
1504      when /\AP([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?T([0-9]+[hH])?([0-9]+[mM])?([0-9]+[sS])?|P([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?/   #V_ISO8601_DURATION PnYnMnWnDTnnHnnMnnS
1505        yield :V_ISO8601_DURATION, $&
1506      when /\A\S/ #UTF8CHAR
1507        yield :UTF8CHAR, $&
1508      end
1509      data = $' # variable $' receives the string after the match
1510    when :dadl
1511      data = scan_dadl(data) do |sym, val|
1512        yield sym, val
1513      end
1514    when :cadl
1515      data = scan_cadl(data) do |sym, val|
1516        yield sym, val
1517      end
1518    when :regexp
1519      data = scan_regexp(data) do |sym, val|
1520        yield sym, val
1521      end
1522    when :term_constraint
1523      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1524
1525      data = scan_term_constraint(data) do |sym, val|
1526        yield sym, val
1527      end
1528    else
1529      raise
1530    end
1531  end
1532end # scan_adl
1533
1534
1535def scan_cadl(data)
1536  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_cadl at #{@filename}:#{@lineno}: data = #{data.inspect}")
1537  until data.nil?  do
1538    case @adl_type.last
1539    when :cadl
1540      case scanned = @@cadl_scanner.parse(data)
1541      when Yaparc::Result::OK
1542        if scanned.value[0] == :START_V_C_DOMAIN_TYPE_BLOCK
1543          @in_c_domain_type = true
1544          @adl_type.push(:dadl)
1545          yield scanned.value
1546        else
1547          yield scanned.value
1548        end
1549        data = scanned.input
1550      end
1551
1552      case data
1553      when /\A\n/ # carriage return
1554        @lineno += 1
1555        ;
1556      when /\A[ \t\r\f]+/ #just drop it
1557        ;
1558      when /\A--.*\n/ # single line comment
1559        @lineno += 1
1560        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1561        ;
1562        ###----------/* symbols */ -------------------------------------------------
1563      when /\A\=/   # =
1564        yield :SYM_EQ, :SYM_EQ
1565      when /\A\>=/   # >=
1566        yield :SYM_GE, :SYM_GE
1567      when /\A\<=/   # <=
1568        yield :SYM_LE, :SYM_LE
1569###       when /\A[A-Z][a-zA-Z0-9_]*[ \n]*\</   # V_C_DOMAIN_TYPE
1570###         @in_c_domain_type = true
1571###         @adl_type.push(:dadl)
1572###         yield :START_V_C_DOMAIN_TYPE_BLOCK, $&
1573      when /\A\</   # <
1574        if @in_interval
1575          yield :SYM_LT, :SYM_LT
1576        else
1577          @adl_type.push(:dadl)
1578          yield :SYM_START_DBLOCK,  $&
1579        end
1580      when /\A\>/   # >
1581        if @in_interval
1582          yield :SYM_GT, :SYM_GT
1583        else
1584          adl_type = @adl_type.pop
1585#          puts "Escaping #{adl_type}"
1586          assert_at(__FILE__,__LINE__){adl_type == :dadl}
1587          yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
1588        end
1589      when /\A\-/   # -
1590        yield :Minus_code, :Minus_code
1591      when /\A\+/   # +
1592        yield :Plus_code, :Plus_code
1593      when /\A\*/   # *
1594        yield :Star_code, :Star_code
1595      when /\A\//   # /
1596        yield :Slash_code, :Slash_code
1597      when /\A\^/   # ^
1598        yield :Caret_code, :Caret_code
1599      when /\A\.\.\./   # ...
1600        yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
1601      when /\A\.\./   # ..
1602        yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
1603      when /\A\./   # .
1604        yield :Dot_code, :Dot_code
1605      when /\A\;/   # ;
1606        yield :Semicolon_code, :Semicolon_code
1607      when /\A\,/   # ,
1608        yield :Comma_code, :Comma_code
1609      when /\A\:/   # :
1610        yield :Colon_code, :Colon_code
1611      when /\A\!/   # !
1612        yield :Exclamation_code, :Exclamation_code
1613      when /\A\(/   # (
1614        yield :Left_parenthesis_code, :Left_parenthesis_code
1615      when /\A\)/   # )
1616        yield :Right_parenthesis_code, :Right_parenthesis_code
1617      when /\A\{\// #V_REGEXP
1618        if @adl_type.last != :regexp
1619          @in_regexp = true
1620          @adl_type.push(:regexp)
1621          yield :START_REGEXP_BLOCK, :START_REGEXP_BLOCK
1622        else
1623          raise
1624        end
1625#        yield :V_REGEXP, :V_REGEXP
1626      when /\A\{/   # {
1627        @adl_type.push(:cadl)
1628        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: entering cADL at #{@filename}:#{@lineno}")
1629        yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
1630      when /\A\}/   # }
1631        adl_type = @adl_type.pop
1632#        puts "Escaping #{adl_type}"
1633        assert_at(__FILE__,__LINE__){adl_type == :cadl}
1634        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: exiting cADL at #{@filename}:#{@lineno}")
1635        yield :SYM_END_CBLOCK, :SYM_END_CBLOCK
1636      when /\A\$/   # $
1637        yield :Dollar_code, :Dollar_code
1638      when /\A\?\?/   # ??
1639        yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
1640      when /\A\?/   # ?
1641        yield :Question_mark_code, :Question_mark_code
1642      when /\A\|/   # |
1643        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
1644        if @in_interval
1645          @in_interval = false
1646        else
1647#          @in_interval = false
1648          @in_interval = true
1649        end
1650        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
1651        yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
1652
1653      when /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/  #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1654#      when /\A\[[a-zA-Z0-9._\-]+::[a-zA-Z0-9._\-]+\]/   #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1655        yield :V_QUALIFIED_TERM_CODE_REF, $&
1656      when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
1657        yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
1658      when /\A\[([a-zA-Z0-9\(\)\._\-]+)::[ \t\n]*/
1659        @adl_type.push(:term_constraint)
1660        yield :START_TERM_CODE_CONSTRAINT, $1
1661      when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
1662        yield :V_LOCAL_TERM_CODE_REF, $&
1663      when /\A\[/   # [
1664        yield :Left_bracket_code, :Left_bracket_code
1665      when /\A\]/   # ]
1666        yield :Right_bracket_code, :Right_bracket_code
1667      when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1668        yield :V_GENERIC_TYPE_IDENTIFIER, $&
1669      when /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X][T\t][hH?X][hH?X]:[mM?X][mM?X]:[sS?X][sS?X]/
1670        yield :V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, $&
1671      when /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/
1672        yield :V_ISO8601_DATE_CONSTRAINT_PATTERN, $&
1673      when /\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/
1674        yield :V_ISO8601_TIME_CONSTRAINT_PATTERN, $&
1675      when /\A[a-z][a-zA-Z0-9_]*/
1676        word = $&.dup
1677        if @@cadl_reserved[word.downcase]
1678          yield @@cadl_reserved[word.downcase], @@cadl_reserved[word.downcase]
1679        else
1680          @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}:#{@lineno}")
1681          yield :V_ATTRIBUTE_IDENTIFIER, word #V_ATTRIBUTE_IDENTIFIER /\A[a-z][a-zA-Z0-9_]*/
1682        end
1683      when /\A[A-Z][a-zA-Z0-9_]*/
1684        word = $&.dup
1685        if @@cadl_reserved[word.downcase]
1686          yield @@cadl_reserved[word.downcase], @@cadl_reserved[word.downcase]
1687        else
1688          yield :V_TYPE_IDENTIFIER, $&
1689        end
1690      when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
1691        yield :V_LOCAL_CODE, $&
1692      when /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](,[0-9]+)?(Z|[+-][0-9]{4})?|[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9](Z|[+-][0-9]{4})?|[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9](Z|[+-][0-9]{4})?/   #V_ISO8601_EXTENDED_DATE_TIME YYYY-MM-DDThh:mm:ss[,sss][Z|+/- -n-n-n-n-]-
1693        yield :V_ISO8601_EXTENDED_DATE_TIME, $&
1694      when /\A[0-2][0-9]:[0-6][0-9]:[0-6][0-9](,[0-9]+)?(Z|[+-][0-9]{4})?|[0-2][0-9]:[0-6][0-9](Z|[+-][0-9]{4})? /   #V_ISO8601_EXTENDED_TIME hh:mm:ss[,sss][Z|+/-nnnn]
1695        yield :V_ISO8601_EXTENDED_TIME, $&
1696      when /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]|[0-9]{4}-[0-1][0-9]/   #V_ISO8601_EXTENDED_DATE YYYY-MM-DD
1697        yield :V_ISO8601_EXTENDED_DATE, $&
1698      when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
1699        yield :V_INTEGER, $&
1700      when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
1701        yield :V_REAL, $&
1702           when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
1703      when /\A"([^"]*)"/m #V_STRING
1704        yield :V_STRING, $1
1705      when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
1706        yield :V_URI, $&
1707###       when /\AP([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?T([0-9]+[hH])?([0-9]+[mM])?([0-9]+[sS])?|P([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?/   #V_ISO8601_DURATION PnYnMnWnDTnnHnnMnnS
1708###         yield :V_ISO8601_DURATION, $&
1709      when /\A\S/ #UTF8CHAR
1710        yield :UTF8CHAR, $&
1711      else
1712        raise
1713      end
1714      data = $' # variable $' receives the string after the match
1715    when :adl
1716      data = scan_adl(data) do |sym, val|
1717        yield sym, val
1718      end
1719    when :dadl
1720      data = scan_dadl(data) do |sym, val|
1721        yield sym, val
1722      end
1723    when :regexp
1724      data = scan_regexp(data) do |sym, val|
1725        yield sym, val
1726      end
1727    when :term_constraint
1728      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1729     
1730      data = scan_term_constraint(data) do |sym, val|
1731        yield sym, val
1732      end
1733    else
1734      raise
1735    end
1736  end # of until
1737end # of scan_cadl
1738
1739def scan_dadl(data)
1740  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_dadl at #{@filename}:#{@lineno}: data = #{data.inspect}")
1741  until data.nil?  do
1742    case @adl_type.last
1743    when :dadl
1744      case scanned = @@dadl_scanner.parse(data)
1745      when Yaparc::Result::OK
1746        yield scanned.value
1747        data = scanned.input
1748      else
1749      end
1750
1751      case data
1752      when /\A\n/ # carriage return
1753        @lineno += 1
1754        ;
1755      when /\A[ \t\r\f]+/ #just drop it
1756        ;
1757      when /\A--.*\n/ # single line comment
1758        @lineno += 1
1759        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1760        ;
1761        ###----------/* symbols */ -------------------------------------------------
1762      when /\A\=/   # =
1763        yield :SYM_EQ, :SYM_EQ
1764      when /\A\>\=/   # >=
1765        yield :SYM_GE, :SYM_GE
1766      when /\A\<\=/   # <=
1767        yield :SYM_LE, :SYM_LE
1768      when /\A\</   # <
1769        if @in_interval
1770          yield :SYM_LT, :SYM_LT
1771        else
1772          @adl_type.push(:dadl)
1773          yield :SYM_START_DBLOCK, :SYM_START_DBLOCK
1774        end
1775      when /\A\>/   # >
1776        if @in_interval
1777#          @in_interval = false
1778          yield :SYM_GT, :SYM_GT
1779        elsif @in_c_domain_type == true
1780          assert_at(__FILE__,__LINE__){@adl_type.last == :dadl}
1781          adl_type = @adl_type.pop
1782          if @adl_type.last == :cadl
1783            @in_c_domain_type = false
1784            yield :END_V_C_DOMAIN_TYPE_BLOCK, $&
1785          else
1786            yield :SYM_END_DBLOCK, $&
1787          end
1788        elsif @in_c_domain_type == false
1789          adl_type = @adl_type.pop
1790          assert_at(__FILE__,__LINE__){adl_type == :dadl}
1791          yield :SYM_END_DBLOCK, $&
1792        else
1793          raise
1794        end
1795      when /\A\-/   # -
1796        yield :Minus_code, :Minus_code
1797      when /\A\+/   # +
1798        yield :Plus_code, :Plus_code
1799      when /\A\*/   # *
1800        yield :Star_code, :Star_code
1801      when /\A\//   # /
1802        yield :Slash_code, :Slash_code
1803      when /\A\^/   # ^
1804        yield :Caret_code, :Caret_code
1805      when /\A\.\.\./   # ...
1806        yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
1807      when /\A\.\./   # ..
1808        yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
1809      when /\A\./   # .
1810        yield :Dot_code, :Dot_code
1811      when /\A\;/   # ;
1812        yield :Semicolon_code, :Semicolon_code
1813      when /\A\,/   # ,
1814        yield :Comma_code, :Comma_code
1815      when /\A\:/   # :
1816        yield :Colon_code, :Colon_code
1817      when /\A\!/   # !
1818        yield :Exclamation_code, :Exclamation_code
1819      when /\A\(/   # (
1820        yield :Left_parenthesis_code, :Left_parenthesis_code
1821      when /\A\)/   # )
1822        yield :Right_parenthesis_code, :Right_parenthesis_code
1823      when /\A\$/   # $
1824        yield :Dollar_code, :Dollar_code
1825      when /\A\?\?/   # ??
1826        yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
1827      when /\A\?/   # ?
1828        yield :Question_mark_code, :Question_mark_code
1829      when /\A\|/   # |
1830        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
1831        if @in_interval
1832          @in_interval = false
1833        else
1834#          @in_interval = false
1835          @in_interval = true
1836        end
1837        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
1838        yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
1839###       when /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/   #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1840###         yield :V_QUALIFIED_TERM_CODE_REF, $&
1841###       when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
1842###         yield :V_LOCAL_TERM_CODE_REF, $&
1843###       when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
1844###         yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
1845      when /\A\[/   # [
1846        yield :Left_bracket_code, :Left_bracket_code
1847      when /\A\]/   # ]
1848        yield :Right_bracket_code, :Right_bracket_code
1849###       when /\A[A-Z][a-zA-Z0-9_-]*/
1850###         yield :V_TYPE_IDENTIFIER, $&
1851###       when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1852###         yield :V_GENERIC_TYPE_IDENTIFIER, $&
1853###       when /\A[a-z][a-zA-Z0-9_]*/
1854###         word = $&.downcase
1855###         if @@dadl_reserved[word]
1856###           yield @@dadl_reserved[word], @@dadl_reserved[word]
1857###         else
1858###           yield :V_ATTRIBUTE_IDENTIFIER, $&
1859###         end
1860###       when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
1861###         yield :V_LOCAL_CODE, $&
1862      when /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](,[0-9]+)?(Z|[+-][0-9]{4})?|[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9](Z|[+-][0-9]{4})?|[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9](Z|[+-][0-9]{4})?/   #V_ISO8601_EXTENDED_DATE_TIME YYYY-MM-DDThh:mm:ss[,sss][Z|+/- -n-n-n-n-]-
1863        yield :V_ISO8601_EXTENDED_DATE_TIME, $&
1864      when /\A[0-2][0-9]:[0-6][0-9]:[0-6][0-9](,[0-9]+)?(Z|[+-][0-9]{4})?|[0-2][0-9]:[0-6][0-9](Z|[+-][0-9]{4})? /   #V_ISO8601_EXTENDED_TIME hh:mm:ss[,sss][Z|+/-nnnn]
1865        yield :V_ISO8601_EXTENDED_TIME, $&
1866      when /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]|[0-9]{4}-[0-1][0-9]/   #V_ISO8601_EXTENDED_DATE YYYY-MM-DD
1867        yield :V_ISO8601_EXTENDED_DATE, $&
1868      when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1869        yield :V_GENERIC_TYPE_IDENTIFIER, $&
1870      when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
1871        yield :V_INTEGER, $&
1872###       when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
1873###         yield :V_REAL, $&
1874        #    when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
1875###       when /\A"([^"]*)"/m #V_STRING
1876###         yield :V_STRING, $1
1877      when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
1878        yield :V_URI, $&
1879###       when /\AP([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?T([0-9]+[hH])?([0-9]+[mM])?([0-9]+[sS])?|P([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?/   #V_ISO8601_DURATION PnYnMnWnDTnnHnnMnnS
1880###         yield :V_ISO8601_DURATION, $&
1881      when /\A\S/ #UTF8CHAR
1882        yield :UTF8CHAR, $&
1883      end
1884      data = $' # variable $' receives the string after the match
1885    when :adl
1886      data = scan_adl(data) do |sym, val|
1887        yield sym, val
1888      end
1889    when :cadl
1890      data = scan_cadl(data) do |sym, val|
1891        yield sym, val
1892      end
1893    when :regexp
1894#      puts "Entering scan_regexp"
1895      data = scan_regexp(data) do |sym, val|
1896        yield sym, val
1897      end
1898    when :term_constraint
1899      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1900
1901      data = scan_term_constraint(data) do |sym, val|
1902        yield sym, val
1903      end
1904    else
1905      raise
1906    end
1907  end
1908end # of scan_dadl
1909
1910def scan_regexp(data)
1911  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_regexp at #{@filename}:#{@lineno}: data = #{data.inspect}")
1912  until data.nil?  do
1913    case @adl_type.last
1914    when :regexp
1915      case data
1916      when /\A\/\}/ #V_REGEXP
1917        if @adl_type.last == :regexp
1918          @in_regexp = false
1919          @adl_type.pop
1920          yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
1921        else
1922          raise
1923        end
1924      when /\A(.*)(\/\})/ #V_REGEXP
1925        yield :REGEXP_BODY, $1
1926        if @adl_type.last == :regexp
1927          @in_regexp = false
1928          @adl_type.pop
1929          yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
1930        else
1931          raise
1932        end
1933      else
1934        raise data
1935      end
1936      data = $' # variable $' receives the string after the match
1937    when :adl
1938      data = scan_adl(data) do |sym, val|
1939        yield sym, val
1940      end
1941    when :dadl
1942      data = scan_dadl(data) do |sym, val|
1943        yield sym, val
1944      end
1945    when :cadl
1946      data = scan_cadl(data) do |sym, val|
1947        yield sym, val
1948      end
1949    when :term_constraint
1950      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_regexp: Entering scan_term_constraint at #{@filename}:#{@lineno}")
1951      data = scan_term_constraint(data) do |sym, val|
1952        yield sym, val
1953      end
1954    else
1955      raise
1956    end
1957  end
1958end # of scan_regexp
1959
1960def scan_term_constraint(data)
1961  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_term_constraint")
1962  until data.nil?  do
1963    case @adl_type.last
1964    when :term_constraint
1965      case data
1966      when /\A\n/ # carriage return
1967        @lineno += 1
1968        ;
1969      when /\A[ \t\r\f]+/ #just drop it
1970        ;
1971      when /\A--.*$/ # single line comment
1972        @lineno += 1
1973        #@@logger.debug("#{__FILE__}:#{__LINE__}: scan_term_constraint: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1974        ;
1975      when /\A([a-zA-Z0-9\._\-])+[ \t]*,/ # match any line, with ',' termination
1976        yield :TERM_CODE, $1
1977      when /\A([a-zA-Z0-9\._\-])+[ \t]*;/ # match second last line with ';' termination (assumed value)
1978        yield :TERM_CODE, $1
1979      when /\A([a-zA-Z0-9\._\-])*[ \t]*\]/ # match final line, terminating in ']'
1980        adl_type = @adl_type.pop
1981        assert_at(__FILE__,__LINE__){adl_type == :term_constraint}
1982        yield :END_TERM_CODE_CONSTRAINT, $1
1983      else
1984        raise "data = #{data}"
1985      end
1986      data = $' # variable $' receives the string after the match
1987    when :adl
1988      data = scan_adl(data) do |sym, val|
1989        yield sym, val
1990      end
1991    when :dadl
1992      data = scan_dadl(data) do |sym, val|
1993        yield sym, val
1994      end
1995    when :cadl
1996      data = scan_cadl(data) do |sym, val|
1997        yield sym, val
1998      end
1999    else
2000      raise
2001    end
2002  end
2003end # of scan_term_constraint
2004
2005
2006def parse(data, filename, lineno = 1, debug = false)
2007  @yydebug = true
2008  @parsestring = data
2009  @data = data
2010  @lineno = lineno
2011  @filename = filename
2012  @adl_type = [:adl] # {:adl, :cadl, :dadl}
2013  @in_regexp = false
2014  @in_interval = false
2015  @in_c_domain_type = false
2016  yyparse self, :scan
2017end
2018
2019def on_error( t, v, values)
2020  raise Racc::ParseError, "#{@filename}:#{@lineno}: Inline syntax error on #{v.inspect}"
2021end
2022
2023
2024
2025
2026
2027
2028
2029### Local Variables:
2030### mode:ruby
2031### mode:font-lock
2032### comment-column:0
2033### comment-start: "### "
2034### comment-end:""
2035### End:
2036
2037
2038
2039
Note: See TracBrowser for help on using the repository browser.