source: ruby/trunk/lib/adl_parser/lib/adl_scanner.rb@ 316

Last change on this file since 316 was 316, checked in by Tatsukawa, Akimichi, 15 years ago

refactoring ADL scanners to handle the syntax more properly

File size: 52.2 KB
Line 
1require 'rubygems'
2require 'logger'
3require 'adl_parser.rb'
4require 'open_ehr'
5#require 'am.rb'
6#require 'rm.rb'
7require 'util.rb'
8
9
10module OpenEhr
11 module ADL
12 module Scanner
13# LOGGER = Logger.new('log/scanner.log')
14 LOGGER = Logger.new('log/parser.log')
15 LOGGER.level = Logger::DEBUG
16
17 class Base
18 attr_accessor :adl_type, :lineno
19 def initialize(adl_type, filename, lineno = 1)
20 @adl_type = adl_type
21 @filename = filename
22 @lineno = lineno
23 end
24
25 def scan(data)
26 raise
27 end
28 end
29
30 #
31 # ADLScanner
32 #
33 class ADLScanner < Base
34 attr_accessor :adl_type, :lineno, :cadl_scanner, :dadl_scanner, :regex_scanner, :term_constraint_scanner
35
36 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')
37 RESERVED = {
38 'archetype' => :SYM_ARCHETYPE,
39 'adl_version' => :SYM_ADL_VERSION,
40 'controlled' => :SYM_IS_CONTROLLED,
41 'specialize' => :SYM_SPECIALIZE,
42 'concept' => :SYM_CONCEPT,
43 'language' => :SYM_LANGUAGE,
44 'description' => :SYM_DESCRIPTION,
45 'definition' => :SYM_DEFINITION,
46 'invariant' => :SYM_INVARIANT,
47 'ontology' => :SYM_ONTOLOGY,
48 'matches' => :SYM_MATCHES,
49 'is_in' => :SYM_MATCHES,
50 'occurrences' => :SYM_OCCURRENCES,
51 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
52 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
53 'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
54 }
55
56 def initialize(adl_type, filename, lineno = 1)
57 super(adl_type, filename, lineno)
58 @in_interval = false
59 end
60
61 #
62 # ADLScanner#scan
63 #
64 def scan(data)
65 @@logger.debug("#{__FILE__}:#{__LINE__}: Entering ADLScanner#scan at #{@filename}:#{@lineno}: data = #{data.inspect}")
66 until data.nil? do
67 case @adl_type.last
68 when :adl
69 case data
70 when /\A\n/ # carriage return
71 @lineno += 1
72 ;
73 when /\A[ \t\r\f]+/ #just drop it
74 ;
75 when /\A--.*/ # single line comment
76 @lineno += 1
77 @@logger.debug("ADLScanner#scan: COMMENT = #{$&} at #{@filename}:#{@lineno}")
78 ;
79 when /\Alanguage/ # language section
80 assert_at(__FILE__,__LINE__){@adl_type.pop == :adl}
81 @adl_type.push(:dadl)
82 yield :SYM_LANGUAGE, :SYM_LANGUAGE
83 when /\Adescription/ # description section
84 assert_at(__FILE__,__LINE__){@adl_type.pop == :dadl}
85 @adl_type.push(:dadl)
86 yield :SYM_DESCRIPTION, :SYM_DESCRIPTION
87 when /\Adefinition/ # definition section
88 assert_at(__FILE__,__LINE__){@adl_type.pop == :dadl}
89 @adl_type.push(:cadl)
90 yield :SYM_DEFINITION, :SYM_DEFINITION
91 when /\Aontology/ # ontology section
92 assert_at(__FILE__,__LINE__){@adl_type.pop == :cadl}
93 @adl_type.push(:dadl)
94 yield :SYM_ONTOLOGY, :SYM_ONTOLOGY
95 when /\Ainvariatn/ # invariant section
96 raise
97 ###----------/* symbols */ -------------------------------------------------
98 when /\A[A-Z][a-zA-Z0-9_]*/
99 yield :V_TYPE_IDENTIFIER, $&
100 when /\A(\w+)-(\w+)-(\w+)\.(\w+)((?:-\w+)*)\.(v\w+)/ #V_ARCHETYPE_ID
101 object_id, rm_originator, rm_name, rm_entity, concept_name, specialisation, version_id = $&, $1, $2, $3, $4, $5, $6
102 #archetype_id = OpenEhr::RM::Support::Identification::ArchetypeID.new(object_id, concept_name, rm_name, rm_entity, rm_originator, specialisation, version_id)
103 archetype_id = OpenEhr::RM::Support::Identification::ArchetypeID.new(:concept_name => concept_name, :rm_name => rm_name, :rm_entity => rm_entity, :rm_originator => :rm_originator, :specialisation => specialisation, :version_id => version_id)
104 yield :V_ARCHETYPE_ID, archetype_id
105 when /\A[a-z][a-zA-Z0-9_]*/
106 word = $&
107 if RESERVED[word]
108 @@logger.debug("ADLScanner#scan: RESERVED = #{RESERVED[word]} at #{@filename}:#{@lineno}")
109 yield RESERVED[word], RESERVED[word]
110 elsif #/\A[A-Z][a-zA-Z0-9_]*/
111 @@logger.debug("ADLScanner#scan: V_ATTRIBUTE_IDENTIFIER = #{$&} at #{@filename}:#{@lineno}")
112 yield :V_ATTRIBUTE_IDENTIFIER, $&
113 end
114 when /\A\=/ # =
115 yield :SYM_EQ, :SYM_EQ
116 when /\A\>=/ # >=
117 yield :SYM_GE, :SYM_GE
118 when /\A\<=/ # <=
119 yield :SYM_LE, :SYM_LE
120 when /\A\</ # <
121 if @in_interval
122 yield :SYM_LT, :SYM_LT
123 else
124 @adl_type.push(:dadl)
125 yield :SYM_START_DBLOCK, $&
126 end
127 when /\A\>/ # >
128 if @in_interval
129 yield :SYM_GT, :SYM_GT
130 else
131 adl_type = @adl_type.pop
132 assert_at(__FILE__,__LINE__){adl_type == :dadl}
133 yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
134 end
135 when /\A\{/ # {
136 @adl_type.push(:cadl)
137 @@logger.debug("ADLScanner#scan: SYM_START_CBLOCK")
138 yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
139 when /\A\}/ # }
140 adl_type = @adl_type.pop
141 assert_at(__FILE__,__LINE__){adl_type == :cadl}
142 @@logger.debug("ADLScanner#scan: SYM_END_CBLOCK")
143 yield :SYM_END_CBLOCK, $&
144 when /\A\-/ # -
145 yield :Minus_code, :Minus_code
146 when /\A\+/ # +
147 yield :Plus_code, :Plus_code
148 when /\A\*/ # *
149 yield :Star_code, :Star_code
150 when /\A\// # /
151 yield :Slash_code, :Slash_code
152 when /\A\^/ # ^
153 yield :Caret_code, :Caret_code
154 when /\A\=/ # =
155 yield :Equal_code, :Equal_code
156 when /\A\.\.\./ # ...
157 yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
158 when /\A\.\./ # ..
159 yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
160 when /\A\./ # .
161 yield :Dot_code, :Dot_code
162 when /\A\;/ # ;
163 yield :Semicolon_code, :Semicolon_code
164 when /\A\,/ # ,
165 yield :Comma_code, :Comma_code
166 when /\A\:/ # :
167 yield :Colon_code, :Colon_code
168 when /\A\!/ # !
169 yield :Exclamation_code, :Exclamation_code
170 when /\A\(/ # (
171 yield :Left_parenthesis_code, :Left_parenthesis_code
172 when /\A\)/ # )
173 yield :Right_parenthesis_code, :Right_parenthesis_code
174 when /\A\$/ # $
175 yield :Dollar_code, :Dollar_code
176 when /\A\?\?/ # ??
177 yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
178 when /\A\?/ # ?
179 yield :Question_mark_code, :Question_mark_code
180 when /\A[0-9]+\.[0-9]+(\.[0-9]+)*/ # ?
181 yield :V_VERSION_STRING, $&
182 when /\A\|/ # |
183 if @in_interval
184 @in_interval = false
185 else
186 @in_interval = true
187 end
188 yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
189 when /\A\[([a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+)\]/ #V_QUALIFIED_TERM_CODE_REF form such as [ICD10AM(1998)::F23]
190 yield :V_QUALIFIED_TERM_CODE_REF, $1
191 when /\A\[([a-zA-Z0-9][a-zA-Z0-9._\-]*)\]/ #V_LOCAL_TERM_CODE_REF
192 yield :V_LOCAL_TERM_CODE_REF, $1
193 when /\A\[/ # [
194 yield :Left_bracket_code, :Left_bracket_code
195 when /\A\]/ # ]
196 yield :Right_bracket_code, :Right_bracket_code
197 when /\A"([^"]*)"/m #V_STRING
198 yield :V_STRING, $1
199 when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/ #ERR_V_QUALIFIED_TERM_CODE_REF
200 yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
201 when /\Aa[ct][0-9.]+/ #V_LOCAL_CODE
202 yield :V_LOCAL_CODE, $&
203 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-]-
204 yield :V_ISO8601_EXTENDED_DATE_TIME, $&
205 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]
206 yield :V_ISO8601_EXTENDED_TIME, $&
207 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
208 yield :V_ISO8601_EXTENDED_DATE, $&
209 when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/ #V_GENERIC_TYPE_IDENTIFIER
210 yield :V_GENERIC_TYPE_IDENTIFIER, $&
211 when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/ #V_INTEGER
212 @@logger.debug("ADLScanner#scan: V_INTEGER = #{$&}")
213 yield :V_INTEGER, $&
214 when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ / #V_REAL
215 yield :V_REAL, $&
216 # when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
217 when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
218 yield :V_URI, $&
219 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
220 yield :V_ISO8601_DURATION, $&
221 when /\A\S/ #UTF8CHAR
222 yield :UTF8CHAR, $&
223 end
224 data = $' # variable $' receives the string after the match
225 when :dadl
226 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
227 data = dadl_scanner.scan(data) do |sym, val|
228 yield sym, val
229 end
230 when :cadl
231 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
232 data = cadl_scanner.scan(data) do |sym, val|
233 yield sym, val
234 end
235 when :regexp
236 regex_scanner = OpenEhr::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
237 data = regex_scanner.scan(data) do |sym, val|
238 yield sym, val
239 end
240 when :term_constraint
241 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
242 data = term_constraint_scanner.scan(data) do |sym, val|
243 yield sym, val
244 end
245 else
246 raise
247 end
248 end
249 end
250 end # of ADLScanner
251
252 #
253 # DADLScanner
254 #
255 class DADLScanner < Base
256 attr_accessor :in_interval, :in_c_domain_type, :dblock_depth
257 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')
258 RESERVED = {
259 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
260 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
261 'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
262 }
263
264 def initialize(adl_type, filename, lineno = 1)
265 super(adl_type, filename, lineno)
266 @in_interval = false
267 @in_c_domain_type = false
268 @dblock_depth = 0
269 end
270
271 #
272 # DADLScanner#scan
273 #
274 def scan(data)
275 @@logger.debug("Entering DADLScanner#scan at #{@filename}:#{@lineno}: @adl_type = #{@adl_type.inspect}, data = #{data.inspect}")
276 until data.nil? do
277 @@logger.debug("#{@filename}:#{@lineno}: DADLScanner#scan:loop data = #{data.inspect}")
278 @@logger.debug("#{@filename}:#{@lineno}: DADLScanner#scan:loop self = \n#{self.to_yaml}")
279 case @adl_type.last
280 when :dadl
281 case data
282 when /\A\n/ # carriage return
283 #@@logger.debug("DADLScanner#scan: carriage return, data = #{data.inspect}")
284 @lineno += 1
285 ;
286 when /\A[ \t\r\f]+/ #just drop it
287 ##@@logger.debug("DADLScanner#scan: white space, data = #{data.inspect}")
288 ;
289 when /\A--.*/ # single line comment
290 @@logger.debug("DADLScanner#scan: COMMENT = #{$&} at #{@filename}:#{@lineno}")
291 ;
292 when /\A[a-z][a-zA-Z0-9_]*/
293 word = $&.dup
294 if RESERVED[word.downcase]
295 yield RESERVED[word.downcase], RESERVED[word.downcase]
296 else
297 @@logger.debug("DADLScanner#scan: V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}:#{@lineno}")
298 yield :V_ATTRIBUTE_IDENTIFIER, word #V_ATTRIBUTE_IDENTIFIER /\A[a-z][a-zA-Z0-9_]*/
299 end
300 ###----------/* symbols */ -------------------------------------------------
301 when /\A\=/ # =
302 yield :SYM_EQ, :SYM_EQ
303 when /\A\>\=/ # >=
304 yield :SYM_GE, :SYM_GE
305 when /\A\<\=/ # <=
306 yield :SYM_LE, :SYM_LE
307 when /\A\</ # <
308 if @in_interval
309 yield :SYM_LT, :SYM_LT
310 else
311 unless @in_c_domain_type
312 @adl_type.push(:dadl)
313 else
314 @dblock_depth += 1
315 end
316 yield :SYM_START_DBLOCK, :SYM_START_DBLOCK
317 end
318 when /\A\>/ # >
319 if @in_interval
320 yield :SYM_GT, :SYM_GT
321 else
322 if @in_c_domain_type
323 assert_at(__FILE__,__LINE__){@adl_type.last == :dadl}
324 @dblock_depth -= 1
325 if @dblock_depth < 0
326 @adl_type.pop
327 @in_c_domain_type = false
328 yield :END_V_C_DOMAIN_TYPE_BLOCK, :END_V_C_DOMAIN_TYPE_BLOCK
329 else
330 yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
331 end
332 else
333 adl_type = @adl_type.pop
334 assert_at(__FILE__,__LINE__){adl_type == :dadl}
335 yield :SYM_END_DBLOCK, $&
336 end
337 end
338 when /\A\-/ # -
339 yield :Minus_code, :Minus_code
340 when /\A\+/ # +
341 yield :Plus_code, :Plus_code
342 when /\A\*/ # *
343 yield :Star_code, :Star_code
344 when /\A\// # /
345 yield :Slash_code, :Slash_code
346 when /\A\^/ # ^
347 yield :Caret_code, :Caret_code
348 when /\A\.\.\./ # ...
349 yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
350 when /\A\.\./ # ..
351 yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
352 when /\A\./ # .
353 yield :Dot_code, :Dot_code
354 when /\A\;/ # ;
355 yield :Semicolon_code, :Semicolon_code
356 when /\A\,/ # ,
357 yield :Comma_code, :Comma_code
358 when /\A\:/ # :
359 yield :Colon_code, :Colon_code
360 when /\A\!/ # !
361 yield :Exclamation_code, :Exclamation_code
362 when /\A\(/ # (
363 yield :Left_parenthesis_code, :Left_parenthesis_code
364 when /\A\)/ # )
365 yield :Right_parenthesis_code, :Right_parenthesis_code
366 when /\A\$/ # $
367 yield :Dollar_code, :Dollar_code
368 when /\A\?\?/ # ??
369 yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
370 when /\A\?/ # ?
371 yield :Question_mark_code, :Question_mark_code
372 when /\A\|/ # |
373 @@logger.debug("DADLScanner#scan: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
374 if @in_interval
375 @in_interval = false
376 else
377 # @in_interval = false
378 @in_interval = true
379 end
380 @@logger.debug("DADLScanner#scan: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
381 yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
382 when /\A\[([a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+)\]/ #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
383 yield :V_QUALIFIED_TERM_CODE_REF, $1
384 when /\A\[/ # [
385 @@logger.debug("DADLScanner#scan: Left_bracket_code at #{@filename}:#{@lineno}")
386 yield :Left_bracket_code, :Left_bracket_code
387 when /\A\]/ # ]
388 @@logger.debug("DADLScanner#scan: Right_bracket_code at #{@filename}:#{@lineno}")
389 yield :Right_bracket_code, :Right_bracket_code
390 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-]-
391 @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_DATE_TIME")
392 yield :V_ISO8601_EXTENDED_DATE_TIME, $&
393 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]
394 @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_TIME")
395 yield :V_ISO8601_EXTENDED_TIME, $&
396 when /\A\d{4}-[0-1][0-9]-[0-3][0-9]|[0-9]{4}-[0-1][0-9]/ #V_ISO8601_EXTENDED_DATE YYYY-MM-DD
397 @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_DATE, #{$&}")
398 yield :V_ISO8601_EXTENDED_DATE, $&
399 when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/ #V_GENERIC_TYPE_IDENTIFIER
400 yield :V_GENERIC_TYPE_IDENTIFIER, $&
401 when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
402 @@logger.debug("DADLScanner#scan: V_STRING, #{$1}")
403 yield :V_STRING, $1
404 when /\A"([^"]*)"/m #V_STRING
405 @@logger.debug("DADLScanner#scan: V_STRING, #{$1}")
406 yield :V_STRING, $1
407 when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ / #V_REAL
408 yield :V_REAL, $&
409 when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/ #V_INTEGER
410 @@logger.debug("DADLScanner#scan: V_INTEGER = #{$&}")
411 yield :V_INTEGER, $&
412 when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
413 yield :V_URI, $&
414 when /\A\S/ #UTF8CHAR
415 yield :UTF8CHAR, $&
416 end
417 data = $' # variable $' receives the string after the match
418 when :adl
419 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
420 data = adl_scanner.scan(data) do |sym, val|
421 yield sym, val
422 end
423 when :cadl
424 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
425 data = cadl_scanner.scan(data) do |sym, val|
426 yield sym, val
427 end
428 when :regexp
429 regex_scanner = OpenEhr::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
430 data = regex_scanner.scan(data) do |sym, val|
431 yield sym, val
432 end
433 when :term_constraint
434 @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
435 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
436 data = term_constraint_scanner.scan(data) do |sym, val|
437 yield sym, val
438 end
439 else
440 raise
441 end
442 end
443 end
444 end # of DADLScanner
445
446
447
448 class CADLScanner < Base
449
450 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log') #Logger.new('log/scanner.log')
451 RESERVED = {
452 'then' => :SYM_THEN, # [Tt][Hh][Ee][Nn]
453 'else' => :SYM_ELSE, # [Ee][Ll][Ss][Ee]
454 'and' => :SYM_AND, # [Aa][Nn][Dd]
455 'or' => :SYM_OR, # [Oo][Rr]
456 'xor' => :SYM_XOR, # [Xx][Oo][Rr]
457 'not' => :SYM_NOT, # [Nn][Oo][Tt]
458 'implies' => :SYM_IMPLIES, # [Ii][Mm][Pp][Ll][Ii][Ee][Ss]
459 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
460 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
461 'forall' => :SYM_FORALL, # [Ff][Oo][Rr][_][Aa][Ll][Ll]
462 'exists' => :SYM_EXISTS, # [Ee][Xx][Ii][Ss][Tt][Ss]
463 'existence' => :SYM_EXISTENCE, # [Ee][Xx][Iu][Ss][Tt][Ee][Nn][Cc][Ee]
464 'occurrences' => :SYM_OCCURRENCES, # [Oo][Cc][Cc][Uu][Rr][Rr][Ee][Nn][Cc][Ee][Ss]
465 'cardinality' => :SYM_CARDINALITY, # [Cc][Aa][Rr][Dd][Ii][Nn][Aa][Ll][Ii][Tt][Yy]
466 'ordered' => :SYM_ORDERED, # [Oo][Rr][Dd][Ee][Rr][Ee][Dd]
467 'unordered' => :SYM_UNORDERED, # [Uu][Nn][Oo][Rr][Dd][Ee][Rr][Ee][Dd]
468 'unique' => :SYM_UNIQUE, # [Uu][Nn][Ii][Qq][Uu][Ee]
469 'matches' => :SYM_MATCHES, # [Mm][Aa][Tt][Cc][Hh][Ee][Ss]
470 'is_in' => :SYM_MATCHES, # [Ii][Ss][_][Ii][Nn]
471 'invariant' => :SYM_INVARIANT, # [Ii][Nn][Vv][Aa][Rr][Ii][Aa][Nn][Tt]
472 'infinity' => :SYM_INFINITY, # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
473 'use_node' => :SYM_USE_NODE, # [Uu][Ss][Ee][_][Nn][Oo][Dd][Ee]
474 'use_archetype' => :SYM_ALLOW_ARCHETYPE, # [Uu][Ss][Ee][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
475 'allow_archetype' => :SYM_ALLOW_ARCHETYPE, # [Aa][Ll][Ll][Oo][Ww][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
476 'include' => :SYM_INCLUDE, # [Ii][Nn][Cc][Ll][Uu][Dd][Ee]
477 'exclude' => :SYM_EXCLUDE # [Ee][Xx][Cc][Ll][Uu][Dd][Ee]
478 }
479
480 def initialize(adl_type, filename, lineno = 1)
481 super(adl_type, filename, lineno)
482 @in_interval = false
483 end
484
485 #
486 # CADLScanner#scan
487 #
488 def scan(data)
489 @@logger.debug("#{__FILE__}:#{__LINE__}: Entering CADLScanner#scan at #{@filename}:#{@lineno}: data = #{data.inspect}")
490 until data.nil? do
491 @@logger.debug("CADLScanner#scan: loop data = #{data.inspect}")
492 case @adl_type.last
493 when :cadl
494 case data
495 when /\A\n/ # carriage return
496 @lineno += 1
497 ;
498 #yield :CR, :CR
499 when /\A[ \t\r\f]+/ #just drop it
500 ;
501 when /\A--.*\n/ # single line comment
502 @lineno += 1
503 ;
504 ###----------/* symbols */ -------------------------------------------------
505 when /\A\=/ # =
506 yield :SYM_EQ, :SYM_EQ
507 when /\A\>=/ # >=
508 yield :SYM_GE, :SYM_GE
509 when /\A\<=/ # <=
510 yield :SYM_LE, :SYM_LE
511 when /\A\</ # <
512 if @in_interval
513 yield :SYM_LT, :SYM_LT
514 else
515 @adl_type.push(:dadl)
516 yield :SYM_START_DBLOCK, $&
517 end
518 when /\A\>/ # >
519 if @in_interval
520 yield :SYM_GT, :SYM_GT
521 else
522 adl_type = @adl_type.pop
523 assert_at(__FILE__,__LINE__){adl_type == :dadl}
524 yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
525 end
526 when /\A\-/ # -
527 yield :Minus_code, :Minus_code
528 when /\A\+/ # +
529 yield :Plus_code, :Plus_code
530 when /\A\*/ # *
531 yield :Star_code, :Star_code
532 when /\A\// # /
533 yield :Slash_code, :Slash_code
534 when /\A\^/ # ^
535 yield :Caret_code, :Caret_code
536 when /\A\.\.\./ # ...
537 yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
538 when /\A\.\./ # ..
539 yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
540 when /\A\./ # .
541 yield :Dot_code, :Dot_code
542 when /\A\;/ # ;
543 yield :Semicolon_code, :Semicolon_code
544 when /\A\,/ # ,
545 yield :Comma_code, :Comma_code
546 when /\A\:/ # :
547 yield :Colon_code, :Colon_code
548 when /\A\!/ # !
549 yield :Exclamation_code, :Exclamation_code
550 when /\A\(/ # (
551 yield :Left_parenthesis_code, :Left_parenthesis_code
552 when /\A\)/ # )
553 yield :Right_parenthesis_code, :Right_parenthesis_code
554 when /\A\{\// #V_REGEXP
555 if @adl_type.last != :regexp
556 @in_regexp = true
557 @adl_type.push(:regexp)
558 yield :START_REGEXP_BLOCK, :START_REGEXP_BLOCK
559 else
560 raise
561 end
562 when /\A\{/ # {
563 @adl_type.push(:cadl)
564 @@logger.debug("CADLScanner#scan: entering cADL at #{@filename}:#{@lineno}")
565 yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
566 when /\A\}/ # }
567 adl_type = @adl_type.pop
568 assert_at(__FILE__,__LINE__){adl_type == :cadl}
569 @@logger.debug("CADLScanner#scan: exiting cADL at #{@filename}:#{@lineno}")
570 yield :SYM_END_CBLOCK, :SYM_END_CBLOCK
571 when /\A\$/ # $
572 yield :Dollar_code, :Dollar_code
573 when /\A\?\?/ # ??
574 yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
575 when /\A\?/ # ?
576 yield :Question_mark_code, :Question_mark_code
577 when /\A\|/ # |
578 @@logger.debug("CADLScanner#scan: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
579 if @in_interval
580 @in_interval = false
581 else
582 # @in_interval = false
583 @in_interval = true
584 end
585 @@logger.debug("CADLScanner#scan: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
586 yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
587
588 when /\A\[([a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+)\]/ #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
589 yield :V_QUALIFIED_TERM_CODE_REF, $1
590 when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/ #ERR_V_QUALIFIED_TERM_CODE_REF
591 yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
592 when /\A\[([a-zA-Z0-9\(\)\._\-]+)::[ \t\n]*/
593 @adl_type.push(:term_constraint)
594 yield :START_TERM_CODE_CONSTRAINT, $1
595 when /\A\[([a-zA-Z0-9][a-zA-Z0-9._\-]*)\]/ #V_LOCAL_TERM_CODE_REF
596 yield :V_LOCAL_TERM_CODE_REF, $1
597 when /\A\[/ # [
598 yield :Left_bracket_code, :Left_bracket_code
599 when /\A\]/ # ]
600 yield :Right_bracket_code, :Right_bracket_code
601 when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/ #V_GENERIC_TYPE_IDENTIFIER
602 yield :V_GENERIC_TYPE_IDENTIFIER, $&
603 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]/
604 yield :V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, $&
605 when /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/
606 yield :V_ISO8601_DATE_CONSTRAINT_PATTERN, $&
607 when /\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/
608 yield :V_ISO8601_TIME_CONSTRAINT_PATTERN, $&
609 #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 such as PnYnMnWnDTnnHnnMnnS
610 when /\AP([0-9]+[yY])?([0-9]+[mM])?([0-9]+[wW])?([0-9]+[dD])?T([0-9]+[hH])?([0-9]+[mM])?([0-9]+[sS])?/ #V_ISO8601_DURATION such as PnYnMnWnDTnnHnnMnnS
611 yield :V_ISO8601_DURATION, $&
612 when /\AP[yY]?[mM]?[wW]?[dD]?T[hH]?[mM]?[sS]?/ #V_ISO8601_DURATION_CONSTRAINT_PATTERNo
613 yield :V_ISO8601_DURATION_CONSTRAINT_PATTERN, $&
614 when /\A[a-z][a-zA-Z0-9_]*/
615 word = $&.dup
616 if RESERVED[word.downcase]
617 yield RESERVED[word.downcase], RESERVED[word.downcase]
618 else
619 @@logger.debug("CADLScanner#scan: V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}:#{@lineno}")
620 yield :V_ATTRIBUTE_IDENTIFIER, word #V_ATTRIBUTE_IDENTIFIER /\A[a-z][a-zA-Z0-9_]*/
621 end
622 when /\A([A-Z][a-zA-Z0-9_]*)[ \n]*\</ # V_C_DOMAIN_TYPE
623 @in_c_domain_type = true
624 @adl_type.push(:dadl)
625 yield :START_V_C_DOMAIN_TYPE_BLOCK, $1
626 when /\A[A-Z][a-zA-Z0-9_]*/
627 word = $&.dup
628 if RESERVED[word.downcase]
629 yield RESERVED[word.downcase], RESERVED[word.downcase]
630 else
631 yield :V_TYPE_IDENTIFIER, $&
632 end
633 when /\Aa[ct][0-9.]+/ #V_LOCAL_CODE
634 yield :V_LOCAL_CODE, $&
635 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-]-
636 yield :V_ISO8601_EXTENDED_DATE_TIME, $&
637 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]
638 yield :V_ISO8601_EXTENDED_TIME, $&
639 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
640 yield :V_ISO8601_EXTENDED_DATE, $&
641 when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
642 yield :V_STRING, $1
643 when /\A"([^"]*)"/m #V_STRING
644 yield :V_STRING, $1
645 when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ / #V_REAL
646 yield :V_REAL, $&
647 when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/ #V_INTEGER
648 @@logger.debug("CADLScanner#scan: V_INTEGER = #{$&}")
649 yield :V_INTEGER, $&
650 when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
651 yield :V_URI, $&
652 when /\A\S/ #UTF8CHAR
653 yield :UTF8CHAR, $&
654 when /\A.+/ #
655 raise OpenEhr::ADL::Exception::CADLScanner::Base.new, "can't handle #{data.inspect}"
656 end
657 data = $' # variable $' receives the string after the match
658 when :adl
659 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
660 data = adl_scanner.scan(data) do |sym, val|
661 yield sym, val
662 end
663 when :dadl
664 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
665 dadl_scanner.in_c_domain_type = @in_c_domain_type
666 data = dadl_scanner.scan(data) do |sym, val|
667 yield sym, val
668 end
669 when :regexp
670 regex_scanner = OpenEhr::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
671 data = regex_scanner.scan(data) do |sym, val|
672 yield sym, val
673 end
674 when :term_constraint
675 @@logger.debug("Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
676 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
677 data = term_constraint_scanner.scan(data) do |sym, val|
678 yield sym, val
679 end
680 else
681 raise OpenEhr::ADL::Exception::CADLScanner.new, "unexpected adl_type: #{@adl_type.last}"
682 end
683 end # of until
684 end
685 end # of CADLScanner
686
687
688 #
689 # RegexScanner
690 #
691 class RegexScanner < Base
692
693 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log') #Logger.new('log/scanner.log')
694
695 def initialize(adl_type, filename, lineno = 1)
696 super(adl_type, filename, lineno)
697 end
698
699 def scan(data)
700 @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_regexp at #{@filename}:#{@lineno}: data = #{data.inspect}")
701 until data.nil? do
702 case @adl_type.last
703 when :regexp
704 case data
705 when /\A\/\}/ #V_REGEXP
706 if @adl_type.last == :regexp
707 @in_regexp = false
708 @adl_type.pop
709 yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
710 else
711 raise
712 end
713 when /\A(.*)(\/\})/ #V_REGEXP
714 yield :REGEXP_BODY, $1
715 if @adl_type.last == :regexp
716 @in_regexp = false
717 @adl_type.pop
718 yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
719 else
720 raise
721 end
722 else
723 raise data
724 end
725 data = $' # variable $' receives the string after the match
726 when :adl
727 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
728 data = adl_scanner.scan(data) do |sym, val|
729 yield sym, val
730 end
731 when :dadl
732 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
733 data = dadl_scanner.scan(data) do |sym, val|
734 yield sym, val
735 end
736 when :cadl
737 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
738 data = cadl_scanner.scan(data) do |sym, val|
739 yield sym, val
740 end
741 when :term_constraint
742 #@@logger.debug("#{__FILE__}:#{__LINE__}: scan_regexp: Entering scan_term_constraint at #{@filename}:#{@lineno}")
743 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
744 data = term_constraint_scanner.scan(data) do |sym, val|
745 yield sym, val
746 end
747 else
748 raise
749 end
750 end
751 end
752 end # of RegexScanner
753
754 #
755 # TermConstraintScanner
756 #
757 class TermConstraintScanner < Base
758 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log') #Logger.new('log/scanner.log')
759 def initialize(adl_type, filename, lineno = 1)
760 super(adl_type, filename, lineno)
761 end
762
763 def scan(data)
764 @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_term_constraint")
765 until data.nil? do
766 case @adl_type.last
767 when :term_constraint
768 case data
769 when /\A\n/ # carriage return
770 @lineno += 1
771 ;
772 when /\A[ \t\r\f]+/ #just drop it
773 ;
774 when /\A--.*$/ # single line comment
775 @lineno += 1
776 @@logger.debug("#{__FILE__}:#{__LINE__}: scan_term_constraint: COMMENT = #{$&} at #{@filename}:#{@lineno}")
777 ;
778 when /\A([a-zA-Z0-9\._\-])+[ \t]*,/ # match any line, with ',' termination
779 yield :TERM_CODE, $1
780 when /\A([a-zA-Z0-9\._\-])+[ \t]*;/ # match second last line with ';' termination (assumed value)
781 yield :TERM_CODE, $1
782 when /\A([a-zA-Z0-9\._\-])*[ \t]*\]/ # match final line, terminating in ']'
783 adl_type = @adl_type.pop
784 assert_at(__FILE__,__LINE__){adl_type == :term_constraint}
785 yield :END_TERM_CODE_CONSTRAINT, $1
786 else
787 raise "data = #{data}"
788 end
789 data = $' # variable $' receives the string after the match
790 when :adl
791 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
792 data = adl_scanner.scan(data) do |sym, val|
793 yield sym, val
794 end
795 when :dadl
796 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
797 data = dadl_scanner.scan(data) do |sym, val|
798 yield sym, val
799 end
800 when :cadl
801 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
802 data = cadl_scanner.scan(data) do |sym, val|
803 yield sym, val
804 end
805 else
806 raise
807 end
808 end
809 end
810 end # of TermConstraintScanner
811
812 end
813 end
814end
815
816__END__
817
818
819
820# module Common
821# class START_TERM_CODE_CONSTRAINT
822# include Yaparc::Parsable
823# def initialize
824# @parser = lambda do |input|
825# Yaparc::Apply.new(Yaparc::Regex.new(/[ \t\n]*\[([a-zA-Z0-9\(\)\._\-]+)::[ \t\n]*/)) do |match|
826# OpenEhr::LOG.info("START_TERM_CODE_CONSTRAINT: #{match}")
827# [:START_TERM_CODE_CONSTRAINT, match]
828# end
829# end
830# end
831# end
832
833# # /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/ #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
834# class V_QUALIFIED_TERM_CODE_REF
835# include Yaparc::Parsable
836# def initialize
837# @parser = lambda do |input|
838# Yaparc::Apply.new(Yaparc::Regex.new(/\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/)) do |match|
839# OpenEhr::LOG.info("V_QUALIFIED_TERM_CODE_REF: #{match}")
840# [:V_QUALIFIED_TERM_CODE_REF, match]
841# end
842# end
843# end
844# end
845
846# class V_LOCAL_TERM_CODE_REF
847# include Yaparc::Parsable
848# def initialize
849# @parser = lambda do |input|
850# Yaparc::Apply.new(Yaparc::Regex.new(/\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/)) do |match|
851# OpenEhr::LOG.info("V_TERM_CODE_REF: #{match}")
852# [:V_LOCAL_TERM_CODE_REF, match]
853# end
854# end
855# end
856# end
857
858# class ERR_V_QUALIFIED_TERM_CODE_REF
859# include Yaparc::Parsable
860# def initialize
861# @parser = lambda do |input|
862# Yaparc::Apply.new(Yaparc::Regex.new(/\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/)) do |match|
863# OpenEhr::LOG.info("ERR_V_QUALIFIED_TERM_CODE_REF: #{match}")
864# [:ERR_V_QUALIFIED_TERM_CODE_REF, match]
865# end
866# end
867# end
868# end
869
870# class V_TYPE_IDENTIFIER
871# include Yaparc::Parsable
872# def initialize
873# @parser = lambda do |input|
874# Yaparc::Apply.new(Yaparc::Regex.new(/\A[A-Z][a-zA-Z0-9_]*/)) do |match|
875# OpenEhr::LOG.info("V_TYPE_IDENTIFIER: #{match}")
876# [:V_TYPE_IDENTIFIER, match]
877# end
878# end
879# end
880# end
881
882# class V_GENERIC_TYPE_IDENTIFIER
883# include Yaparc::Parsable
884# def initialize
885# @parser = lambda do |input|
886# Yaparc::Apply.new(Yaparc::Regex.new(/\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/)) do |match|
887# OpenEhr::LOG.info("V_GENERIC_TYPE_IDENTIFIER: #{match}")
888# [:V_GENERIC_TYPE_IDENTIFIER, match]
889# end
890# end
891# end
892# end
893
894
895# class V_LOCAL_CODE
896# include Yaparc::Parsable
897# def initialize
898# @parser = lambda do |input|
899# Yaparc::Apply.new(Yaparc::Regex.new(/\Aa[ct][0-9.]+/)) do |match|
900# OpenEhr::LOG.info("V_LOCAL_CODE: #{match}")
901# [:V_LOCAL_CODE, match]
902# end
903# end
904# end
905# end
906
907# class V_STRING
908# include Yaparc::Parsable
909# def initialize
910# @parser = lambda do |input|
911# Yaparc::Apply.new(Yaparc::Regex.new(/\A"([^"]*)"/m)) do |match|
912# OpenEhr::LOG.info("V_STRING: #{match}")
913# [:V_STRING, match]
914# end
915# end
916# end
917# end
918
919# class V_REAL
920# include Yaparc::Parsable
921# def initialize
922# @parser = lambda do |input|
923# Yaparc::Apply.new(Yaparc::Regex.new(/\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+/)) do |match|
924# OpenEhr::LOG.info("V_REAL: #{match}")
925# [:V_REAL, match]
926# end
927# end
928# end
929# end
930
931# #V_ISO8601_DURATION PnYnMnWnDTnnHnnMnnS
932# class V_ISO8601_DURATION
933# include Yaparc::Parsable
934# def initialize
935# @parser = lambda do |input|
936# Yaparc::Apply.new(
937# Yaparc::Alt.new(Yaparc::Regex.new(/\AP([0-9]+|[yY])?([0-9]+|[mM])?([0-9]+|[wW])?([0-9]+|[dD])?T([0-9]+|[hH])?([0-9]+|[mM])?([0-9]+|[sS])?/),
938# Yaparc::Regex.new(/\AP([0-9]+|[yY])?([0-9]+|[mM])?([0-9]+|[wW])?([0-9]+|[dD])?/))) do |match|
939# OpenEhr::LOG.info("V_ISO8601_DURATION: #{match}")
940# [:V_ISO8601_DURATION, match]
941# end
942# end
943# end
944# end
945
946# end # of Common
947
948# module DADL
949# # c.f. http://www.openehr.org/svn/ref_impl_eiffel/TRUNK/components/adl_parser/src/syntax/adl/parser/adl_scanner.l
950# RESERVED = {
951# 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
952# 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
953# 'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
954# }
955# #
956# # DADL::RootScanner
957# #
958# class RootScanner
959# include Yaparc::Parsable
960# def initialize
961# @parser = lambda do |input|
962# Yaparc::Alt.new(Reserved.new,
963# OpenEhr::ADL::Scanner::Common::V_QUALIFIED_TERM_CODE_REF.new,
964# OpenEhr::ADL::Scanner::Common::V_LOCAL_TERM_CODE_REF.new,
965# OpenEhr::ADL::Scanner::Common::ERR_V_QUALIFIED_TERM_CODE_REF.new,
966# OpenEhr::ADL::Scanner::Common::V_TYPE_IDENTIFIER.new,
967# OpenEhr::ADL::Scanner::Common::V_GENERIC_TYPE_IDENTIFIER.new,
968# OpenEhr::ADL::Scanner::Common::V_STRING.new,
969# OpenEhr::ADL::Scanner::Common::V_LOCAL_CODE.new,
970# OpenEhr::ADL::Scanner::Common::V_REAL.new,
971# OpenEhr::ADL::Scanner::Common::V_ISO8601_DURATION.new#,
972# #OpenEhr::ADL::Scanner::Common::START_TERM_CODE_CONSTRAINT.new
973# )
974# end
975# end
976# end
977
978# # <DADL::Reserved class>
979# class Reserved
980# include Yaparc::Parsable
981
982# def initialize
983# @parser = lambda do |input|
984# reserved_parsers = OpenEhr::ADL::Scanner::DADL::RESERVED.map do |keyword|
985# Yaparc::Tokenize.new(
986# Yaparc::Literal.new(keyword[0],false)
987# )
988# end
989# Yaparc::Alt.new(Yaparc::Apply.new(Yaparc::Alt.new(*reserved_parsers)) do |match|
990# OpenEhr::LOG.info("Reserved: #{match}")
991# [OpenEhr::ADL::Scanner::DADL::RESERVED[match], OpenEhr::ADL::Scanner::DADL::RESERVED[match]]
992# end,
993# Yaparc::Apply.new(Yaparc::Regex.new(/\A[a-z][a-zA-Z0-9_]*/)) do |match|
994# OpenEhr::LOG.info("V_ATTRIBUTE_IDENTIFIER: #{match}")
995# [:V_ATTRIBUTE_IDENTIFIER, match]
996# end)
997# end
998# end
999# end
1000# end # of DADL
1001
1002# module CADL
1003# # c.f. http://www.openehr.org/svn/ref_impl_eiffel/TRUNK/components/adl_parser/src/syntax/cadl/parser/cadl_scanner.l
1004# RESERVED = {
1005# 'ordered' => :SYM_ORDERED, # [Oo][Rr][Dd][Ee][Rr][Ee][Dd]
1006# 'unordered' => :SYM_UNORDERED, # [Uu][Nn][Oo][Rr][Dd][Ee][Rr][Ee][Dd]
1007# 'then' => :SYM_THEN, # [Tt][Hh][Ee][Nn]
1008# 'else' => :SYM_ELSE, # [Ee][Ll][Ss][Ee]
1009# 'and' => :SYM_AND, # [Aa][Nn][Dd]
1010# 'or' => :SYM_OR, # [Oo][Rr]
1011# 'xor' => :SYM_XOR, # [Xx][Oo][Rr]
1012# 'not' => :SYM_NOT, # [Nn][Oo][Tt]
1013# 'implies' => :SYM_IMPLIES, # [Ii][Mm][Pp][Ll][Ii][Ee][Ss]
1014# 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
1015# 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
1016# 'forall' => :SYM_FORALL, # [Ff][Oo][Rr][_][Aa][Ll][Ll]
1017# 'exists' => :SYM_EXISTS, # [Ee][Xx][Ii][Ss][Tt][Ss]
1018# 'existence' => :SYM_EXISTENCE, # [Ee][Xx][Iu][Ss][Tt][Ee][Nn][Cc][Ee]
1019# 'occurrences' => :SYM_OCCURRENCES, # [Oo][Cc][Cc][Uu][Rr][Rr][Ee][Nn][Cc][Ee][Ss]
1020# 'cardinality' => :SYM_CARDINALITY, # [Cc][Aa][Rr][Dd][Ii][Nn][Aa][Ll][Ii][Tt][Yy]
1021# 'unique' => :SYM_UNIQUE, # [Uu][Nn][Ii][Qq][Uu][Ee]
1022# 'matches' => :SYM_MATCHES, # [Mm][Aa][Tt][Cc][Hh][Ee][Ss]
1023# 'is_in' => :SYM_MATCHES, # [Ii][Ss][_][Ii][Nn]
1024# 'invariant' => :SYM_INVARIANT, # [Ii][Nn][Vv][Aa][Rr][Ii][Aa][Nn][Tt]
1025# 'infinity' => :SYM_INFINITY, # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
1026# 'use_node' => :SYM_USE_NODE, # [Uu][Ss][Ee][_][Nn][Oo][Dd][Ee]
1027# 'use_archetype' => :SYM_ALLOW_ARCHETYPE, # [Uu][Ss][Ee][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
1028# 'allow_archetype' => :SYM_ALLOW_ARCHETYPE, # [Aa][Ll][Ll][Oo][Ww][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
1029# 'include' => :SYM_INCLUDE, # [Ii][Nn][Cc][Ll][Uu][Dd][Ee]
1030# 'exclude' => :SYM_EXCLUDE # [Ee][Xx][Cc][Ll][Uu][Dd][Ee]
1031# }
1032
1033# #V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, /\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]/
1034# class V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN
1035# include Yaparc::Parsable
1036# def initialize
1037# @parser = lambda do |input|
1038# Yaparc::Apply.new(Yaparc::Regex.new(/\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]/)) do |match|
1039# OpenEhr::LOG.info("V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN: #{match}")
1040# [:V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, match]
1041# end
1042# end
1043# end
1044# end
1045
1046# #V_ISO8601_DATE_CONSTRAINT_PATTERN /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/
1047# class V_ISO8601_DATE_CONSTRAINT_PATTERN
1048# include Yaparc::Parsable
1049# def initialize
1050# @parser = lambda do |input|
1051# Yaparc::Apply.new(Yaparc::Regex.new(/\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/)) do |match|
1052# OpenEhr::LOG.info("V_ISO8601_DATE_CONSTRAINT_PATTERN: #{match}")
1053# [:V_ISO8601_DATE_CONSTRAINT_PATTERN, match]
1054# end
1055# end
1056# end
1057# end
1058
1059# #V_ISO8601_TIME_CONSTRAINT_PATTERN /\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/
1060# class V_ISO8601_TIME_CONSTRAINT_PATTERN
1061# include Yaparc::Parsable
1062# def initialize
1063# @parser = lambda do |input|
1064# Yaparc::Apply.new(Yaparc::Regex.new(/\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/)) do |match|
1065# OpenEhr::LOG.info("V_ISO8601_TIME_CONSTRAINT_PATTERN: #{match}")
1066# [:V_ISO8601_TIME_CONSTRAINT_PATTERN, match]
1067# end
1068# end
1069# end
1070# end
1071
1072# #V_ISO8601_DURATION_CONSTRAINT_PATTERN
1073# class V_ISO8601_DURATION_CONSTRAINT_PATTERN
1074# include Yaparc::Parsable
1075# def initialize
1076# @parser = lambda do |input|
1077# Yaparc::Apply.new(Yaparc::Alt.new(Yaparc::Regex.new(/\AP[yY]?[mM]?[wW]?[dD]?T[hH]?[mM]?[sS]?/),
1078# Yaparc::Regex.new(/\AP[yY]?[mM]?[wW]?[dD]?/))) do |match|
1079# OpenEhr::LOG.info("V_ISO8601_DURATION_CONSTRAINT_PATTERN: #{match}")
1080# [:V_ISO8601_DURATION_CONSTRAINT_PATTERN, match]
1081# end
1082# end
1083# end
1084# end
1085
1086# #V_C_DOMAIN_TYPE /\A[A-Z][a-zA-Z0-9_]*[ \n]*\</
1087# class V_C_DOMAIN_TYPE
1088# include Yaparc::Parsable
1089# def initialize
1090# @parser = lambda do |input|
1091# Yaparc::Apply.new(Yaparc::Regex.new(/\A[A-Z][a-zA-Z0-9_]*[ \n]*\</)) do |match|
1092# OpenEhr::LOG.info("V_C_DOMAIN_TYPE: #{match}")
1093# [:START_V_C_DOMAIN_TYPE_BLOCK, match]
1094# end
1095# end
1096# end
1097# end
1098
1099# #
1100# # CADL::RootScanner
1101# #
1102# class RootScanner
1103# include Yaparc::Parsable
1104# def initialize
1105# @parser = lambda do |input|
1106# Yaparc::Alt.new(V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN.new,
1107# V_ISO8601_DATE_CONSTRAINT_PATTERN.new,
1108# V_ISO8601_TIME_CONSTRAINT_PATTERN.new,
1109# OpenEhr::ADL::Scanner::Common::V_ISO8601_DURATION.new,
1110# V_C_DOMAIN_TYPE.new,
1111# V_ISO8601_DURATION_CONSTRAINT_PATTERN.new,
1112# Reserved.new,
1113# OpenEhr::ADL::Scanner::Common::V_QUALIFIED_TERM_CODE_REF.new,
1114# OpenEhr::ADL::Scanner::Common::V_LOCAL_TERM_CODE_REF.new,
1115# OpenEhr::ADL::Scanner::Common::ERR_V_QUALIFIED_TERM_CODE_REF.new,
1116# OpenEhr::ADL::Scanner::Common::V_TYPE_IDENTIFIER.new,
1117# OpenEhr::ADL::Scanner::Common::V_GENERIC_TYPE_IDENTIFIER.new,
1118# OpenEhr::ADL::Scanner::Common::V_STRING.new,
1119# OpenEhr::ADL::Scanner::Common::V_LOCAL_CODE.new,
1120# OpenEhr::ADL::Scanner::Common::V_REAL.new,
1121# OpenEhr::ADL::Scanner::Common::V_ISO8601_DURATION.new#,
1122# #OpenEhr::ADL::Scanner::Common::START_TERM_CODE_CONSTRAINT.new
1123# )
1124# end
1125# end
1126# end
1127
1128# # <CADL::Reserved class>
1129# class Reserved
1130# include Yaparc::Parsable
1131
1132# def initialize
1133# @parser = lambda do |input|
1134# orderd_reserved = RESERVED.keys.sort{|x,y| y.length <=> x.length }
1135# reserved_parsers = orderd_reserved.map do |keyword|
1136# Yaparc::Literal.new(keyword,false)
1137# end
1138# Yaparc::Alt.new(Yaparc::Apply.new(Yaparc::Alt.new(*reserved_parsers)) do |match|
1139# OpenEhr::LOG.info("Reserved: #{match}")
1140# [OpenEhr::ADL::Scanner::CADL::RESERVED[match], OpenEhr::ADL::Scanner::CADL::RESERVED[match]]
1141# end,
1142# Yaparc::Apply.new(Yaparc::Regex.new(/\A[a-z][a-zA-Z0-9_]*/)) do |match|
1143# OpenEhr::LOG.info("V_ATTRIBUTE_IDENTIFIER: #{match}")
1144# [:V_ATTRIBUTE_IDENTIFIER, match]
1145# end)
1146# end
1147# end
1148# end
1149
1150# end
1151
1152
Note: See TracBrowser for help on using the repository browser.