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

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

changed log level setting at parser.y

File size: 65.2 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'
1196#require 'lib/adl_parser.rb'
1197require 'rubygems'
1198require 'adl_parser.rb'
1199require 'am.rb'
1200require 'rm.rb'
1201$DEBUG = true
1202
1203
1204
1205---- inner
1206
1207def assert_at(file,line, message = "")
1208  unless yield
1209    raise "Assertion failed !: #{file}, #{line}: #{message}"
1210  end
1211end
1212
1213if $DEBUG
1214  @@logger = Logger.new('log/parser.log','daily')
1215  @@logger.level = Logger::DEBUG
1216else
1217  @@logger = Logger.new(STDOUT)
1218  @@logger.level = Logger::WARN
1219end
1220
1221@@dadl_scanner = OpenEHR::ADL::Scanner::DADL::RootScanner.new
1222@@cadl_scanner = OpenEHR::ADL::Scanner::CADL::RootScanner.new
1223
1224###----------/* keywords */ ---------------------------------------------
1225@@adl_reserved = {
1226    'archetype' => :SYM_ARCHETYPE,
1227    'adl_version' => :SYM_ADL_VERSION,
1228    'controlled' => :SYM_IS_CONTROLLED,
1229    'specialize' => :SYM_SPECIALIZE,
1230    'concept' => :SYM_CONCEPT,
1231    'language' => :SYM_LANGUAGE,
1232    'description' => :SYM_DESCRIPTION,
1233    'definition' => :SYM_DEFINITION,
1234    'invariant' => :SYM_INVARIANT,
1235    'ontology' => :SYM_ONTOLOGY,
1236    'matches' => :SYM_MATCHES,
1237    'is_in' => :SYM_MATCHES,
1238    'occurrences' => :SYM_OCCURRENCES,
1239    'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1240    'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1241    'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1242}
1243
1244@@dadl_reserved = {
1245  'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1246  'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1247  'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1248}
1249
1250@@cadl_reserved = {
1251  'then' => :SYM_THEN, # [Tt][Hh][Ee][Nn]
1252  'else' => :SYM_ELSE, # [Ee][Ll][Ss][Ee]
1253  'and' => :SYM_AND, # [Aa][Nn][Dd]
1254  'or' => :SYM_OR, # [Oo][Rr]
1255  'xor' => :SYM_XOR, # [Xx][Oo][Rr]
1256  'not' => :SYM_NOT, # [Nn][Oo][Tt]
1257  'implies' => :SYM_IMPLIES, # [Ii][Mm][Pp][Ll][Ii][Ee][Ss]
1258  'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1259  'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1260  'forall' => :SYM_FORALL, # [Ff][Oo][Rr][_][Aa][Ll][Ll]
1261  'exists' => :SYM_EXISTS, # [Ee][Xx][Ii][Ss][Tt][Ss]
1262  'existence' => :SYM_EXISTENCE, # [Ee][Xx][Iu][Ss][Tt][Ee][Nn][Cc][Ee]
1263  'occurrences' => :SYM_OCCURRENCES, # [Oo][Cc][Cc][Uu][Rr][Rr][Ee][Nn][Cc][Ee][Ss]
1264  'cardinality' => :SYM_CARDINALITY, # [Cc][Aa][Rr][Dd][Ii][Nn][Aa][Ll][Ii][Tt][Yy]
1265  'ordered' => :SYM_ORDERED, # [Oo][Rr][Dd][Ee][Rr][Ee][Dd]
1266  'unordered' => :SYM_UNORDERED, # [Uu][Nn][Oo][Rr][Dd][Ee][Rr][Ee][Dd]
1267  'unique' => :SYM_UNIQUE, # [Uu][Nn][Ii][Qq][Uu][Ee]
1268  'matches' => :SYM_MATCHES, # [Mm][Aa][Tt][Cc][Hh][Ee][Ss]
1269  'is_in' => :SYM_MATCHES, # [Ii][Ss][_][Ii][Nn]
1270  'invariant' => :SYM_INVARIANT, # [Ii][Nn][Vv][Aa][Rr][Ii][Aa][Nn][Tt]
1271  'infinity' => :SYM_INFINITY, # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1272  'use_node' => :SYM_USE_NODE, # [Uu][Ss][Ee][_][Nn][Oo][Dd][Ee]
1273  'use_archetype' => :SYM_ALLOW_ARCHETYPE, # [Uu][Ss][Ee][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
1274  'allow_archetype' => :SYM_ALLOW_ARCHETYPE, # [Aa][Ll][Ll][Oo][Ww][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
1275  'include' => :SYM_INCLUDE, # [Ii][Nn][Cc][Ll][Uu][Dd][Ee]
1276  'exclude' => :SYM_EXCLUDE # [Ee][Xx][Cc][Ll][Uu][Dd][Ee]
1277}
1278
1279
1280###----------/* Scanner */ -----------------------------------------------
1281
1282def scan
1283  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan at #{@filename}:#{@lineno}:")
1284  until @data.nil?  do
1285    case @adl_type.last
1286    when :adl
1287      @data = scan_adl(@data) do |sym, val|
1288        yield sym, val
1289      end
1290    when :dadl
1291      @data = scan_dadl(@data) do |sym, val|
1292        yield sym, val
1293      end
1294    when :cadl
1295      @data = scan_cadl(@data) do |sym, val|
1296        yield sym, val
1297      end
1298    when :regexp
1299      @data = scan_regexp(@data) do |sym, val|
1300        yield sym, val
1301      end
1302    when :term_constraint
1303      @@logger.debug("#{__FILE__}:#{__LINE__}: scan: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1304      @data = scan_term_constraint(@data) do |sym, val|
1305        yield sym, val
1306      end
1307    else
1308      raise
1309    end
1310    @data = $' # variable $' receives the string after the match
1311  end
1312  yield :EOF, nil
1313  yield false, '$'
1314end # of scan
1315
1316def scan_adl(data)
1317  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_adl at #{@filename}:#{@lineno}: data = #{data.inspect}")
1318  until data.nil?  do
1319    case @adl_type.last
1320    when :adl
1321      case data
1322      when /\A\n/ # carriage return
1323        @lineno += 1
1324        ;
1325      when /\A[ \t\r\f]+/ #just drop it
1326        ;
1327      when /\A--.*\n/ # single line comment
1328        @lineno += 1
1329        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1330        ;
1331      when /\Adescription/   # description
1332        yield :SYM_DESCRIPTION, :SYM_DESCRIPTION
1333      when /\Adefinition/   # definition
1334        yield :SYM_DEFINITION, :SYM_DEFINITION
1335        ###----------/* symbols */ -------------------------------------------------
1336      when /\A[A-Z][a-zA-Z0-9_]*/
1337        yield :V_TYPE_IDENTIFIER, $&
1338#      when /\A[a-zA-Z][a-zA-Z0-9_-]+\.[a-zA-Z][a-zA-Z0-9_-]+\.[a-zA-Z0-9]+/   #V_ARCHETYPE_ID
1339      when /\A(\w+)-(\w+)-(\w+)\.(\w+)(-\w+)?\.(v\w+)/   #V_ARCHETYPE_ID
1340        object_id, rm_originator, rm_name, rm_entity, concept_name, specialisation, version_id = $&, $1, $2, $3, $4, $5, $6
1341        archetype_id = OpenEHR::RM::Support::Identification::Archetype_ID.new(object_id, concept_name, rm_name, rm_entity, rm_originator, specialisation, version_id)
1342#        yield :V_ARCHETYPE_ID, $&
1343        yield :V_ARCHETYPE_ID, archetype_id
1344      when /\A[a-z][a-zA-Z0-9_]*/
1345#        word = $&.downcase
1346        word = $&
1347        if @@adl_reserved[word]
1348          @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: @@adl_reserved = #{@@adl_reserved[word]} at #{@filename}:#{@lineno}")
1349          yield @@adl_reserved[word], @@adl_reserved[word]
1350        elsif #/\A[A-Z][a-zA-Z0-9_]*/
1351          @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: V_ATTRIBUTE_IDENTIFIER = #{$&} at #{@filename}:#{@lineno}")
1352          yield :V_ATTRIBUTE_IDENTIFIER, $&
1353        end
1354      when /\A\=/   # =
1355        yield :SYM_EQ, :SYM_EQ
1356      when /\A\>=/   # >=
1357        yield :SYM_GE, :SYM_GE
1358      when /\A\<=/   # <=
1359        yield :SYM_LE, :SYM_LE
1360      when /\A\</   # <
1361        if @in_interval
1362#          @start_block_received = false
1363          yield :SYM_LT, :SYM_LT
1364        else
1365#          @start_block_received = true
1366          @adl_type.push(:dadl)
1367          yield :SYM_START_DBLOCK,  $&
1368        end
1369      when /\A\>/   # >
1370        if @in_interval
1371          yield :SYM_GT, :SYM_GT
1372        else
1373          adl_type = @adl_type.pop
1374          assert_at(__FILE__,__LINE__){adl_type == :dadl}
1375          yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
1376        end
1377      when /\A\{/   # {
1378        @adl_type.push(:cadl)
1379        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: entering cADL at #{@filename}:#{@lineno}")
1380        yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
1381      when /\A\}/   # }
1382        adl_type = @adl_type.pop
1383#        puts "Escaping #{adl_type}"
1384        assert_at(__FILE__,__LINE__){adl_type == :cadl}
1385        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: exiting cADL at #{@filename}:#{@lineno}")
1386        yield :SYM_END_CBLOCK, $&
1387      when /\A\-/   # -
1388        yield :Minus_code, :Minus_code
1389      when /\A\+/   # +
1390        yield :Plus_code, :Plus_code
1391      when /\A\*/   # *
1392        yield :Star_code, :Star_code
1393      when /\A\//   # /
1394        yield :Slash_code, :Slash_code
1395      when /\A\^/   # ^
1396        yield :Caret_code, :Caret_code
1397      when /\A\=/   # =
1398        yield :Equal_code, :Equal_code
1399      when /\A\.\.\./   # ...
1400        yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
1401      when /\A\.\./   # ..
1402        yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
1403      when /\A\./   # .
1404        yield :Dot_code, :Dot_code
1405      when /\A\;/   # ;
1406        yield :Semicolon_code, :Semicolon_code
1407      when /\A\,/   # ,
1408        yield :Comma_code, :Comma_code
1409      when /\A\:/   # :
1410        yield :Colon_code, :Colon_code
1411      when /\A\!/   # !
1412        yield :Exclamation_code, :Exclamation_code
1413      when /\A\(/   # (
1414        yield :Left_parenthesis_code, :Left_parenthesis_code
1415      when /\A\)/   # )
1416        yield :Right_parenthesis_code, :Right_parenthesis_code
1417      when /\A\$/   # $
1418        yield :Dollar_code, :Dollar_code
1419      when /\A\?\?/   # ??
1420        yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
1421      when /\A\?/   # ?
1422        yield :Question_mark_code, :Question_mark_code
1423      when /\A[0-9]+\.[0-9]+(\.[0-9]+)*/   # ?
1424        yield :V_VERSION_STRING, $&
1425      when /\A\|/   # |
1426        if @in_interval
1427          @in_interval = false
1428        else
1429          @in_interval = true
1430        end
1431        yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
1432      when /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/
1433#      when /\A\[[a-zA-Z0-9()\._-]+\:\:[a-zA-Z0-9\._-]+\]/   #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1434        yield :V_QUALIFIED_TERM_CODE_REF, $&
1435      when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
1436        yield :V_LOCAL_TERM_CODE_REF, $&
1437      when /\A\[/   # [
1438        yield :Left_bracket_code, :Left_bracket_code
1439      when /\A\]/   # ]
1440        yield :Right_bracket_code, :Right_bracket_code
1441
1442      when /\A"([^"]*)"/m #V_STRING
1443        yield :V_STRING, $1
1444      when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
1445        yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
1446      when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
1447        yield :V_LOCAL_CODE, $&
1448      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-]-
1449        yield :V_ISO8601_EXTENDED_DATE_TIME, $&
1450      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]
1451        yield :V_ISO8601_EXTENDED_TIME, $&
1452      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
1453        yield :V_ISO8601_EXTENDED_DATE, $&
1454      when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1455        yield :V_GENERIC_TYPE_IDENTIFIER, $&
1456      when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
1457        yield :V_INTEGER, $&
1458      when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
1459        yield :V_REAL, $&
1460        #    when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
1461      when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
1462        yield :V_URI, $&
1463      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
1464        yield :V_ISO8601_DURATION, $&
1465      when /\A\S/ #UTF8CHAR
1466        yield :UTF8CHAR, $&
1467      end
1468      data = $' # variable $' receives the string after the match
1469    when :dadl
1470      data = scan_dadl(data) do |sym, val|
1471        yield sym, val
1472      end
1473    when :cadl
1474      data = scan_cadl(data) do |sym, val|
1475        yield sym, val
1476      end
1477    when :regexp
1478      data = scan_regexp(data) do |sym, val|
1479        yield sym, val
1480      end
1481    when :term_constraint
1482      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1483
1484      data = scan_term_constraint(data) do |sym, val|
1485        yield sym, val
1486      end
1487    else
1488      raise
1489    end
1490  end
1491end # scan_adl
1492
1493
1494def scan_cadl(data)
1495  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_cadl at #{@filename}:#{@lineno}: data = #{data.inspect}")
1496  until data.nil?  do
1497    case @adl_type.last
1498    when :cadl
1499      case scanned = @@cadl_scanner.parse(data)
1500      when Yaparc::Result::OK
1501        if scanned.value[0] == :START_V_C_DOMAIN_TYPE_BLOCK
1502          @in_c_domain_type = true
1503          @adl_type.push(:dadl)
1504          yield scanned.value
1505        else
1506          yield scanned.value
1507        end
1508        data = scanned.input
1509      end
1510
1511      case data
1512      when /\A\n/ # carriage return
1513        @lineno += 1
1514        ;
1515      when /\A[ \t\r\f]+/ #just drop it
1516        ;
1517      when /\A--.*\n/ # single line comment
1518        @lineno += 1
1519        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1520        ;
1521        ###----------/* symbols */ -------------------------------------------------
1522      when /\A\=/   # =
1523        yield :SYM_EQ, :SYM_EQ
1524      when /\A\>=/   # >=
1525        yield :SYM_GE, :SYM_GE
1526      when /\A\<=/   # <=
1527        yield :SYM_LE, :SYM_LE
1528###       when /\A[A-Z][a-zA-Z0-9_]*[ \n]*\</   # V_C_DOMAIN_TYPE
1529###         @in_c_domain_type = true
1530###         @adl_type.push(:dadl)
1531###         yield :START_V_C_DOMAIN_TYPE_BLOCK, $&
1532      when /\A\</   # <
1533        if @in_interval
1534          yield :SYM_LT, :SYM_LT
1535        else
1536          @adl_type.push(:dadl)
1537          yield :SYM_START_DBLOCK,  $&
1538        end
1539      when /\A\>/   # >
1540        if @in_interval
1541          yield :SYM_GT, :SYM_GT
1542        else
1543          adl_type = @adl_type.pop
1544#          puts "Escaping #{adl_type}"
1545          assert_at(__FILE__,__LINE__){adl_type == :dadl}
1546          yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
1547        end
1548      when /\A\-/   # -
1549        yield :Minus_code, :Minus_code
1550      when /\A\+/   # +
1551        yield :Plus_code, :Plus_code
1552      when /\A\*/   # *
1553        yield :Star_code, :Star_code
1554      when /\A\//   # /
1555        yield :Slash_code, :Slash_code
1556      when /\A\^/   # ^
1557        yield :Caret_code, :Caret_code
1558      when /\A\.\.\./   # ...
1559        yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
1560      when /\A\.\./   # ..
1561        yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
1562      when /\A\./   # .
1563        yield :Dot_code, :Dot_code
1564      when /\A\;/   # ;
1565        yield :Semicolon_code, :Semicolon_code
1566      when /\A\,/   # ,
1567        yield :Comma_code, :Comma_code
1568      when /\A\:/   # :
1569        yield :Colon_code, :Colon_code
1570      when /\A\!/   # !
1571        yield :Exclamation_code, :Exclamation_code
1572      when /\A\(/   # (
1573        yield :Left_parenthesis_code, :Left_parenthesis_code
1574      when /\A\)/   # )
1575        yield :Right_parenthesis_code, :Right_parenthesis_code
1576      when /\A\{\// #V_REGEXP
1577        if @adl_type.last != :regexp
1578          @in_regexp = true
1579          @adl_type.push(:regexp)
1580          yield :START_REGEXP_BLOCK, :START_REGEXP_BLOCK
1581        else
1582          raise
1583        end
1584#        yield :V_REGEXP, :V_REGEXP
1585      when /\A\{/   # {
1586        @adl_type.push(:cadl)
1587        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: entering cADL at #{@filename}:#{@lineno}")
1588        yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
1589      when /\A\}/   # }
1590        adl_type = @adl_type.pop
1591#        puts "Escaping #{adl_type}"
1592        assert_at(__FILE__,__LINE__){adl_type == :cadl}
1593        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: exiting cADL at #{@filename}:#{@lineno}")
1594        yield :SYM_END_CBLOCK, :SYM_END_CBLOCK
1595      when /\A\$/   # $
1596        yield :Dollar_code, :Dollar_code
1597      when /\A\?\?/   # ??
1598        yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
1599      when /\A\?/   # ?
1600        yield :Question_mark_code, :Question_mark_code
1601      when /\A\|/   # |
1602        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
1603        if @in_interval
1604          @in_interval = false
1605        else
1606#          @in_interval = false
1607          @in_interval = true
1608        end
1609        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
1610        yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
1611
1612      when /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/  #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1613#      when /\A\[[a-zA-Z0-9._\-]+::[a-zA-Z0-9._\-]+\]/   #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1614        yield :V_QUALIFIED_TERM_CODE_REF, $&
1615      when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
1616        yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
1617      when /\A\[([a-zA-Z0-9\(\)\._\-]+)::[ \t\n]*/
1618        @adl_type.push(:term_constraint)
1619        yield :START_TERM_CODE_CONSTRAINT, $1
1620      when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
1621        yield :V_LOCAL_TERM_CODE_REF, $&
1622      when /\A\[/   # [
1623        yield :Left_bracket_code, :Left_bracket_code
1624      when /\A\]/   # ]
1625        yield :Right_bracket_code, :Right_bracket_code
1626      when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1627        yield :V_GENERIC_TYPE_IDENTIFIER, $&
1628      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]/
1629        yield :V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, $&
1630      when /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/
1631        yield :V_ISO8601_DATE_CONSTRAINT_PATTERN, $&
1632      when /\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/
1633        yield :V_ISO8601_TIME_CONSTRAINT_PATTERN, $&
1634      when /\A[a-z][a-zA-Z0-9_]*/
1635        word = $&.dup
1636        if @@cadl_reserved[word.downcase]
1637          yield @@cadl_reserved[word.downcase], @@cadl_reserved[word.downcase]
1638        else
1639          @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}:#{@lineno}")
1640          yield :V_ATTRIBUTE_IDENTIFIER, word #V_ATTRIBUTE_IDENTIFIER /\A[a-z][a-zA-Z0-9_]*/
1641        end
1642      when /\A[A-Z][a-zA-Z0-9_]*/
1643        word = $&.dup
1644        if @@cadl_reserved[word.downcase]
1645          yield @@cadl_reserved[word.downcase], @@cadl_reserved[word.downcase]
1646        else
1647          yield :V_TYPE_IDENTIFIER, $&
1648        end
1649      when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
1650        yield :V_LOCAL_CODE, $&
1651      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-]-
1652        yield :V_ISO8601_EXTENDED_DATE_TIME, $&
1653      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]
1654        yield :V_ISO8601_EXTENDED_TIME, $&
1655      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
1656        yield :V_ISO8601_EXTENDED_DATE, $&
1657      when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
1658        yield :V_INTEGER, $&
1659      when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
1660        yield :V_REAL, $&
1661           when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
1662      when /\A"([^"]*)"/m #V_STRING
1663        yield :V_STRING, $1
1664      when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
1665        yield :V_URI, $&
1666###       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
1667###         yield :V_ISO8601_DURATION, $&
1668      when /\A\S/ #UTF8CHAR
1669        yield :UTF8CHAR, $&
1670      else
1671        raise
1672      end
1673      data = $' # variable $' receives the string after the match
1674    when :adl
1675      data = scan_adl(data) do |sym, val|
1676        yield sym, val
1677      end
1678    when :dadl
1679      data = scan_dadl(data) do |sym, val|
1680        yield sym, val
1681      end
1682    when :regexp
1683      data = scan_regexp(data) do |sym, val|
1684        yield sym, val
1685      end
1686    when :term_constraint
1687      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1688     
1689      data = scan_term_constraint(data) do |sym, val|
1690        yield sym, val
1691      end
1692    else
1693      raise
1694    end
1695  end # of until
1696end # of scan_cadl
1697
1698def scan_dadl(data)
1699  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_dadl at #{@filename}:#{@lineno}: data = #{data.inspect}")
1700  until data.nil?  do
1701    case @adl_type.last
1702    when :dadl
1703      case scanned = @@dadl_scanner.parse(data)
1704      when Yaparc::Result::OK
1705        yield scanned.value
1706        data = scanned.input
1707      else
1708      end
1709
1710      case data
1711      when /\A\n/ # carriage return
1712        @lineno += 1
1713        ;
1714      when /\A[ \t\r\f]+/ #just drop it
1715        ;
1716      when /\A--.*\n/ # single line comment
1717        @lineno += 1
1718        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1719        ;
1720        ###----------/* symbols */ -------------------------------------------------
1721      when /\A\=/   # =
1722        yield :SYM_EQ, :SYM_EQ
1723      when /\A\>\=/   # >=
1724        yield :SYM_GE, :SYM_GE
1725      when /\A\<\=/   # <=
1726        yield :SYM_LE, :SYM_LE
1727      when /\A\</   # <
1728        if @in_interval
1729          yield :SYM_LT, :SYM_LT
1730        else
1731          @adl_type.push(:dadl)
1732          yield :SYM_START_DBLOCK, :SYM_START_DBLOCK
1733        end
1734      when /\A\>/   # >
1735        if @in_interval
1736#          @in_interval = false
1737          yield :SYM_GT, :SYM_GT
1738        elsif @in_c_domain_type == true
1739          assert_at(__FILE__,__LINE__){@adl_type.last == :dadl}
1740          adl_type = @adl_type.pop
1741          if @adl_type.last == :cadl
1742            @in_c_domain_type = false
1743            yield :END_V_C_DOMAIN_TYPE_BLOCK, $&
1744          else
1745            yield :SYM_END_DBLOCK, $&
1746          end
1747        elsif @in_c_domain_type == false
1748          adl_type = @adl_type.pop
1749          assert_at(__FILE__,__LINE__){adl_type == :dadl}
1750          yield :SYM_END_DBLOCK, $&
1751        else
1752          raise
1753        end
1754      when /\A\-/   # -
1755        yield :Minus_code, :Minus_code
1756      when /\A\+/   # +
1757        yield :Plus_code, :Plus_code
1758      when /\A\*/   # *
1759        yield :Star_code, :Star_code
1760      when /\A\//   # /
1761        yield :Slash_code, :Slash_code
1762      when /\A\^/   # ^
1763        yield :Caret_code, :Caret_code
1764      when /\A\.\.\./   # ...
1765        yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
1766      when /\A\.\./   # ..
1767        yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
1768      when /\A\./   # .
1769        yield :Dot_code, :Dot_code
1770      when /\A\;/   # ;
1771        yield :Semicolon_code, :Semicolon_code
1772      when /\A\,/   # ,
1773        yield :Comma_code, :Comma_code
1774      when /\A\:/   # :
1775        yield :Colon_code, :Colon_code
1776      when /\A\!/   # !
1777        yield :Exclamation_code, :Exclamation_code
1778      when /\A\(/   # (
1779        yield :Left_parenthesis_code, :Left_parenthesis_code
1780      when /\A\)/   # )
1781        yield :Right_parenthesis_code, :Right_parenthesis_code
1782      when /\A\$/   # $
1783        yield :Dollar_code, :Dollar_code
1784      when /\A\?\?/   # ??
1785        yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
1786      when /\A\?/   # ?
1787        yield :Question_mark_code, :Question_mark_code
1788      when /\A\|/   # |
1789        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
1790        if @in_interval
1791          @in_interval = false
1792        else
1793#          @in_interval = false
1794          @in_interval = true
1795        end
1796        @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
1797        yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
1798###       when /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/   #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
1799###         yield :V_QUALIFIED_TERM_CODE_REF, $&
1800###       when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
1801###         yield :V_LOCAL_TERM_CODE_REF, $&
1802###       when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
1803###         yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
1804      when /\A\[/   # [
1805        yield :Left_bracket_code, :Left_bracket_code
1806      when /\A\]/   # ]
1807        yield :Right_bracket_code, :Right_bracket_code
1808###       when /\A[A-Z][a-zA-Z0-9_-]*/
1809###         yield :V_TYPE_IDENTIFIER, $&
1810###       when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1811###         yield :V_GENERIC_TYPE_IDENTIFIER, $&
1812###       when /\A[a-z][a-zA-Z0-9_]*/
1813###         word = $&.downcase
1814###         if @@dadl_reserved[word]
1815###           yield @@dadl_reserved[word], @@dadl_reserved[word]
1816###         else
1817###           yield :V_ATTRIBUTE_IDENTIFIER, $&
1818###         end
1819###       when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
1820###         yield :V_LOCAL_CODE, $&
1821      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-]-
1822        yield :V_ISO8601_EXTENDED_DATE_TIME, $&
1823      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]
1824        yield :V_ISO8601_EXTENDED_TIME, $&
1825      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
1826        yield :V_ISO8601_EXTENDED_DATE, $&
1827      when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
1828        yield :V_GENERIC_TYPE_IDENTIFIER, $&
1829      when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
1830        yield :V_INTEGER, $&
1831###       when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
1832###         yield :V_REAL, $&
1833        #    when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
1834###       when /\A"([^"]*)"/m #V_STRING
1835###         yield :V_STRING, $1
1836      when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
1837        yield :V_URI, $&
1838###       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
1839###         yield :V_ISO8601_DURATION, $&
1840      when /\A\S/ #UTF8CHAR
1841        yield :UTF8CHAR, $&
1842      end
1843      data = $' # variable $' receives the string after the match
1844    when :adl
1845      data = scan_adl(data) do |sym, val|
1846        yield sym, val
1847      end
1848    when :cadl
1849      data = scan_cadl(data) do |sym, val|
1850        yield sym, val
1851      end
1852    when :regexp
1853#      puts "Entering scan_regexp"
1854      data = scan_regexp(data) do |sym, val|
1855        yield sym, val
1856      end
1857    when :term_constraint
1858      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
1859
1860      data = scan_term_constraint(data) do |sym, val|
1861        yield sym, val
1862      end
1863    else
1864      raise
1865    end
1866  end
1867end # of scan_dadl
1868
1869def scan_regexp(data)
1870  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_regexp at #{@filename}:#{@lineno}: data = #{data.inspect}")
1871  until data.nil?  do
1872    case @adl_type.last
1873    when :regexp
1874      case data
1875      when /\A\/\}/ #V_REGEXP
1876        if @adl_type.last == :regexp
1877          @in_regexp = false
1878          @adl_type.pop
1879          yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
1880        else
1881          raise
1882        end
1883      when /\A(.*)(\/\})/ #V_REGEXP
1884        yield :REGEXP_BODY, $1
1885        if @adl_type.last == :regexp
1886          @in_regexp = false
1887          @adl_type.pop
1888          yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
1889        else
1890          raise
1891        end
1892      else
1893        raise data
1894      end
1895      data = $' # variable $' receives the string after the match
1896    when :adl
1897      data = scan_adl(data) do |sym, val|
1898        yield sym, val
1899      end
1900    when :dadl
1901      data = scan_dadl(data) do |sym, val|
1902        yield sym, val
1903      end
1904    when :cadl
1905      data = scan_cadl(data) do |sym, val|
1906        yield sym, val
1907      end
1908    when :term_constraint
1909      @@logger.debug("#{__FILE__}:#{__LINE__}: scan_regexp: Entering scan_term_constraint at #{@filename}:#{@lineno}")
1910      data = scan_term_constraint(data) do |sym, val|
1911        yield sym, val
1912      end
1913    else
1914      raise
1915    end
1916  end
1917end # of scan_regexp
1918
1919def scan_term_constraint(data)
1920  @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_term_constraint")
1921  until data.nil?  do
1922    case @adl_type.last
1923    when :term_constraint
1924      case data
1925      when /\A\n/ # carriage return
1926        @lineno += 1
1927        ;
1928      when /\A[ \t\r\f]+/ #just drop it
1929        ;
1930      when /\A--.*$/ # single line comment
1931        @lineno += 1
1932        #@@logger.debug("#{__FILE__}:#{__LINE__}: scan_term_constraint: COMMENT = #{$&} at #{@filename}:#{@lineno}")
1933        ;
1934      when /\A([a-zA-Z0-9\._\-])+[ \t]*,/ # match any line, with ',' termination
1935        yield :TERM_CODE, $1
1936      when /\A([a-zA-Z0-9\._\-])+[ \t]*;/ # match second last line with ';' termination (assumed value)
1937        yield :TERM_CODE, $1
1938      when /\A([a-zA-Z0-9\._\-])*[ \t]*\]/ # match final line, terminating in ']'
1939        adl_type = @adl_type.pop
1940        assert_at(__FILE__,__LINE__){adl_type == :term_constraint}
1941        yield :END_TERM_CODE_CONSTRAINT, $1
1942      else
1943        raise "data = #{data}"
1944      end
1945      data = $' # variable $' receives the string after the match
1946    when :adl
1947      data = scan_adl(data) do |sym, val|
1948        yield sym, val
1949      end
1950    when :dadl
1951      data = scan_dadl(data) do |sym, val|
1952        yield sym, val
1953      end
1954    when :cadl
1955      data = scan_cadl(data) do |sym, val|
1956        yield sym, val
1957      end
1958    else
1959      raise
1960    end
1961  end
1962end # of scan_term_constraint
1963
1964
1965def parse(data, filename, lineno = 1, debug = false)
1966  @yydebug = true
1967  @parsestring = data
1968  @data = data
1969  @lineno = lineno
1970  @filename = filename
1971  @adl_type = [:adl] # {:adl, :cadl, :dadl}
1972  @in_regexp = false
1973  @in_interval = false
1974  @in_c_domain_type = false
1975  yyparse self, :scan
1976end
1977
1978def on_error( t, v, values)
1979  raise Racc::ParseError, "#{@filename}:#{@lineno}: Inline syntax error on #{v.inspect}"
1980end
1981
1982
1983
1984
1985
1986
1987
1988### Local Variables:
1989### mode:ruby
1990### mode:font-lock
1991### comment-column:0
1992### comment-start: "### "
1993### comment-end:""
1994### End:
1995
1996
1997
1998
Note: See TracBrowser for help on using the repository browser.