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

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

refactoring adl scanners in object-oriented way in progress

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