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
RevLine 
[17]1require 'rubygems'
[265]2require 'logger'
3require 'adl_parser.rb'
[307]4require 'open_ehr'
[314]5#require 'am.rb'
6#require 'rm.rb'
[283]7require 'util.rb'
[17]8
9
[307]10module OpenEhr
[17]11 module ADL
12 module Scanner
[314]13# LOGGER = Logger.new('log/scanner.log')
14 LOGGER = Logger.new('log/parser.log')
[307]15 LOGGER.level = Logger::DEBUG
[265]16
17 class Base
[283]18 attr_accessor :adl_type, :lineno
[265]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
[283]30 #
31 # ADLScanner
32 #
33 class ADLScanner < Base
[314]34 attr_accessor :adl_type, :lineno, :cadl_scanner, :dadl_scanner, :regex_scanner, :term_constraint_scanner
[265]35
[307]36 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')
[265]37 RESERVED = {
[283]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,
[265]51 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
52 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
[283]53 'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
[265]54 }
55
56 def initialize(adl_type, filename, lineno = 1)
57 super(adl_type, filename, lineno)
[283]58 @in_interval = false
[265]59 end
60
[283]61 #
62 # ADLScanner#scan
63 #
[265]64 def scan(data)
[283]65 @@logger.debug("#{__FILE__}:#{__LINE__}: Entering ADLScanner#scan at #{@filename}:#{@lineno}: data = #{data.inspect}")
[265]66 until data.nil? do
[314]67 case @adl_type.last
68 when :adl
[265]69 case data
70 when /\A\n/ # carriage return
71 @lineno += 1
72 ;
73 when /\A[ \t\r\f]+/ #just drop it
74 ;
[283]75 when /\A--.*/ # single line comment
[265]76 @lineno += 1
[283]77 @@logger.debug("ADLScanner#scan: COMMENT = #{$&} at #{@filename}:#{@lineno}")
[265]78 ;
[316]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)
[283]86 yield :SYM_DESCRIPTION, :SYM_DESCRIPTION
[316]87 when /\Adefinition/ # definition section
88 assert_at(__FILE__,__LINE__){@adl_type.pop == :dadl}
89 @adl_type.push(:cadl)
[283]90 yield :SYM_DEFINITION, :SYM_DEFINITION
[316]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
[283]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
[314]102 #archetype_id = OpenEhr::RM::Support::Identification::ArchetypeID.new(object_id, concept_name, rm_name, rm_entity, rm_originator, specialisation, version_id)
[307]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)
[283]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
[265]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
[314]124 @adl_type.push(:dadl)
[265]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
[283]135 when /\A\{/ # {
[314]136 @adl_type.push(:cadl)
137 @@logger.debug("ADLScanner#scan: SYM_START_CBLOCK")
[283]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, $&
[265]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
[283]154 when /\A\=/ # =
155 yield :Equal_code, :Equal_code
[265]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
[283]180 when /\A[0-9]+\.[0-9]+(\.[0-9]+)*/ # ?
181 yield :V_VERSION_STRING, $&
[265]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
[283]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
[307]191 when /\A\[([a-zA-Z0-9][a-zA-Z0-9._\-]*)\]/ #V_LOCAL_TERM_CODE_REF
192 yield :V_LOCAL_TERM_CODE_REF, $1
[265]193 when /\A\[/ # [
194 yield :Left_bracket_code, :Left_bracket_code
195 when /\A\]/ # ]
196 yield :Right_bracket_code, :Right_bracket_code
[283]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, $&
[265]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, $&
[283]209 when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/ #V_GENERIC_TYPE_IDENTIFIER
210 yield :V_GENERIC_TYPE_IDENTIFIER, $&
[265]211 when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/ #V_INTEGER
[283]212 @@logger.debug("ADLScanner#scan: V_INTEGER = #{$&}")
[265]213 yield :V_INTEGER, $&
214 when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ / #V_REAL
215 yield :V_REAL, $&
[283]216 # when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
[265]217 when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
218 yield :V_URI, $&
[283]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, $&
[265]221 when /\A\S/ #UTF8CHAR
222 yield :UTF8CHAR, $&
223 end
224 data = $' # variable $' receives the string after the match
[314]225 when :dadl
226 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
227 data = dadl_scanner.scan(data) do |sym, val|
[283]228 yield sym, val
229 end
[314]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
[265]247 end
[283]248 end
[265]249 end
[283]250 end # of ADLScanner
[265]251
[283]252 #
253 # DADLScanner
254 #
[265]255 class DADLScanner < Base
[314]256 attr_accessor :in_interval, :in_c_domain_type, :dblock_depth
[307]257 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')
[265]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
[314]264 def initialize(adl_type, filename, lineno = 1)
[265]265 super(adl_type, filename, lineno)
[283]266 @in_interval = false
[265]267 @in_c_domain_type = false
[314]268 @dblock_depth = 0
[265]269 end
270
[283]271 #
272 # DADLScanner#scan
273 #
[265]274 def scan(data)
[314]275 @@logger.debug("Entering DADLScanner#scan at #{@filename}:#{@lineno}: @adl_type = #{@adl_type.inspect}, data = #{data.inspect}")
[265]276 until data.nil? do
[314]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
[265]281 case data
282 when /\A\n/ # carriage return
[283]283 #@@logger.debug("DADLScanner#scan: carriage return, data = #{data.inspect}")
[265]284 @lineno += 1
285 ;
286 when /\A[ \t\r\f]+/ #just drop it
[315]287 ##@@logger.debug("DADLScanner#scan: white space, data = #{data.inspect}")
[265]288 ;
[283]289 when /\A--.*/ # single line comment
290 @@logger.debug("DADLScanner#scan: COMMENT = #{$&} at #{@filename}:#{@lineno}")
[265]291 ;
[283]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
[265]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
[314]311 unless @in_c_domain_type
312 @adl_type.push(:dadl)
313 else
314 @dblock_depth += 1
315 end
[265]316 yield :SYM_START_DBLOCK, :SYM_START_DBLOCK
317 end
318 when /\A\>/ # >
319 if @in_interval
320 yield :SYM_GT, :SYM_GT
[314]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
[265]332 else
[314]333 adl_type = @adl_type.pop
334 assert_at(__FILE__,__LINE__){adl_type == :dadl}
335 yield :SYM_END_DBLOCK, $&
[265]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\|/ # |
[283]373 @@logger.debug("DADLScanner#scan: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
[265]374 if @in_interval
375 @in_interval = false
376 else
377 # @in_interval = false
378 @in_interval = true
379 end
[283]380 @@logger.debug("DADLScanner#scan: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
[265]381 yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
[283]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
[265]384 when /\A\[/ # [
[283]385 @@logger.debug("DADLScanner#scan: Left_bracket_code at #{@filename}:#{@lineno}")
[265]386 yield :Left_bracket_code, :Left_bracket_code
387 when /\A\]/ # ]
[283]388 @@logger.debug("DADLScanner#scan: Right_bracket_code at #{@filename}:#{@lineno}")
[265]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-]-
[283]391 @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_DATE_TIME")
[265]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]
[283]394 @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_TIME")
[265]395 yield :V_ISO8601_EXTENDED_TIME, $&
[283]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, #{$&}")
[265]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, $&
[283]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
[315]407 when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ / #V_REAL
408 yield :V_REAL, $&
[265]409 when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/ #V_INTEGER
[283]410 @@logger.debug("DADLScanner#scan: V_INTEGER = #{$&}")
[265]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
[307]419 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
[283]420 data = adl_scanner.scan(data) do |sym, val|
[265]421 yield sym, val
422 end
[283]423 when :cadl
[307]424 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
[283]425 data = cadl_scanner.scan(data) do |sym, val|
[265]426 yield sym, val
427 end
[283]428 when :regexp
[307]429 regex_scanner = OpenEhr::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
[283]430 data = regex_scanner.scan(data) do |sym, val|
[265]431 yield sym, val
432 end
433 when :term_constraint
[283]434 @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
[307]435 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
[283]436 data = term_constraint_scanner.scan(data) do |sym, val|
[265]437 yield sym, val
438 end
439 else
440 raise
441 end
442 end
443 end
[283]444 end # of DADLScanner
[265]445
446
447
[283]448 class CADLScanner < Base
[265]449
[307]450 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log') #Logger.new('log/scanner.log')
[265]451 RESERVED = {
[283]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]
[265]459 'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
460 'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
[283]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]
[265]478 }
479
480 def initialize(adl_type, filename, lineno = 1)
481 super(adl_type, filename, lineno)
[283]482 @in_interval = false
[265]483 end
484
[283]485 #
486 # CADLScanner#scan
487 #
[265]488 def scan(data)
[283]489 @@logger.debug("#{__FILE__}:#{__LINE__}: Entering CADLScanner#scan at #{@filename}:#{@lineno}: data = #{data.inspect}")
[265]490 until data.nil? do
[283]491 @@logger.debug("CADLScanner#scan: loop data = #{data.inspect}")
[265]492 case @adl_type.last
493 when :cadl
494 case data
495 when /\A\n/ # carriage return
496 @lineno += 1
497 ;
[283]498 #yield :CR, :CR
[265]499 when /\A[ \t\r\f]+/ #just drop it
500 ;
501 when /\A--.*\n/ # single line comment
502 @lineno += 1
503 ;
[283]504 ###----------/* symbols */ -------------------------------------------------
[265]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\</ # <
[283]512 if @in_interval
[265]513 yield :SYM_LT, :SYM_LT
[283]514 else
[265]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
[283]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
[265]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\|/ # |
[283]578 @@logger.debug("CADLScanner#scan: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
[265]579 if @in_interval
580 @in_interval = false
581 else
[283]582 # @in_interval = false
[265]583 @in_interval = true
584 end
[283]585 @@logger.debug("CADLScanner#scan: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
[265]586 yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
[283]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
[307]595 when /\A\[([a-zA-Z0-9][a-zA-Z0-9._\-]*)\]/ #V_LOCAL_TERM_CODE_REF
596 yield :V_LOCAL_TERM_CODE_REF, $1
[265]597 when /\A\[/ # [
598 yield :Left_bracket_code, :Left_bracket_code
599 when /\A\]/ # ]
600 yield :Right_bracket_code, :Right_bracket_code
[283]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
[307]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
[283]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
[265]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, $&
[283]641 when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
642 yield :V_STRING, $1
643 when /\A"([^"]*)"/m #V_STRING
644 yield :V_STRING, $1
[315]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, $&
[265]650 when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
651 yield :V_URI, $&
652 when /\A\S/ #UTF8CHAR
653 yield :UTF8CHAR, $&
[283]654 when /\A.+/ #
[307]655 raise OpenEhr::ADL::Exception::CADLScanner::Base.new, "can't handle #{data.inspect}"
[265]656 end
657 data = $' # variable $' receives the string after the match
[283]658 when :adl
[307]659 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
[283]660 data = adl_scanner.scan(data) do |sym, val|
661 yield sym, val
662 end
663 when :dadl
[307]664 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
665 dadl_scanner.in_c_domain_type = @in_c_domain_type
[283]666 data = dadl_scanner.scan(data) do |sym, val|
667 yield sym, val
668 end
669 when :regexp
[307]670 regex_scanner = OpenEhr::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
[283]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}")
[307]676 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
[283]677 data = term_constraint_scanner.scan(data) do |sym, val|
678 yield sym, val
679 end
[265]680 else
[307]681 raise OpenEhr::ADL::Exception::CADLScanner.new, "unexpected adl_type: #{@adl_type.last}"
[265]682 end
[283]683 end # of until
[265]684 end
[283]685 end # of CADLScanner
[265]686
687
[283]688 #
689 # RegexScanner
690 #
691 class RegexScanner < Base
[261]692
[307]693 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log') #Logger.new('log/scanner.log')
[19]694
[283]695 def initialize(adl_type, filename, lineno = 1)
696 super(adl_type, filename, lineno)
[17]697 end
[18]698
[283]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
[18]724 end
[283]725 data = $' # variable $' receives the string after the match
726 when :adl
[307]727 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
[283]728 data = adl_scanner.scan(data) do |sym, val|
729 yield sym, val
730 end
731 when :dadl
[307]732 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
[283]733 data = dadl_scanner.scan(data) do |sym, val|
734 yield sym, val
735 end
736 when :cadl
[307]737 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
[283]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}")
[307]743 term_constraint_scanner = OpenEhr::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
[283]744 data = term_constraint_scanner.scan(data) do |sym, val|
745 yield sym, val
746 end
747 else
748 raise
[18]749 end
750 end
751 end
[283]752 end # of RegexScanner
[18]753
[283]754 #
755 # TermConstraintScanner
756 #
757 class TermConstraintScanner < Base
[307]758 @@logger = OpenEhr::ADL::Scanner::LOGGER #Logger.new('log/scanner.log') #Logger.new('log/scanner.log')
[283]759 def initialize(adl_type, filename, lineno = 1)
760 super(adl_type, filename, lineno)
[18]761 end
762
[283]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}"
[18]788 end
[283]789 data = $' # variable $' receives the string after the match
790 when :adl
[307]791 adl_scanner = OpenEhr::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
[283]792 data = adl_scanner.scan(data) do |sym, val|
793 yield sym, val
794 end
795 when :dadl
[307]796 dadl_scanner = OpenEhr::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
[283]797 data = dadl_scanner.scan(data) do |sym, val|
798 yield sym, val
799 end
800 when :cadl
[307]801 cadl_scanner = OpenEhr::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
[283]802 data = cadl_scanner.scan(data) do |sym, val|
803 yield sym, val
804 end
805 else
806 raise
[18]807 end
808 end
809 end
[283]810 end # of TermConstraintScanner
[18]811
[283]812 end
813 end
814end
[18]815
[283]816__END__
[18]817
818
819
[283]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|
[307]826# OpenEhr::LOG.info("START_TERM_CODE_CONSTRAINT: #{match}")
[283]827# [:START_TERM_CODE_CONSTRAINT, match]
828# end
829# end
830# end
831# end
[19]832
[283]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|
[307]839# OpenEhr::LOG.info("V_QUALIFIED_TERM_CODE_REF: #{match}")
[283]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|
[307]851# OpenEhr::LOG.info("V_TERM_CODE_REF: #{match}")
[283]852# [:V_LOCAL_TERM_CODE_REF, match]
853# end
854# end
855# end
856# end
[19]857
[283]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|
[307]863# OpenEhr::LOG.info("ERR_V_QUALIFIED_TERM_CODE_REF: #{match}")
[283]864# [:ERR_V_QUALIFIED_TERM_CODE_REF, match]
865# end
866# end
867# end
868# end
[261]869
[283]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|
[307]875# OpenEhr::LOG.info("V_TYPE_IDENTIFIER: #{match}")
[283]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|
[307]887# OpenEhr::LOG.info("V_GENERIC_TYPE_IDENTIFIER: #{match}")
[283]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|
[307]900# OpenEhr::LOG.info("V_LOCAL_CODE: #{match}")
[283]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|
[307]912# OpenEhr::LOG.info("V_STRING: #{match}")
[283]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|
[307]924# OpenEhr::LOG.info("V_REAL: #{match}")
[283]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|
[307]939# OpenEhr::LOG.info("V_ISO8601_DURATION: #{match}")
[283]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,
[307]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
[283]973# )
974# end
975# end
976# end
977
978# # <DADL::Reserved class>
979# class Reserved
980# include Yaparc::Parsable
[19]981
[283]982# def initialize
983# @parser = lambda do |input|
[307]984# reserved_parsers = OpenEhr::ADL::Scanner::DADL::RESERVED.map do |keyword|
[283]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|
[307]990# OpenEhr::LOG.info("Reserved: #{match}")
991# [OpenEhr::ADL::Scanner::DADL::RESERVED[match], OpenEhr::ADL::Scanner::DADL::RESERVED[match]]
[283]992# end,
993# Yaparc::Apply.new(Yaparc::Regex.new(/\A[a-z][a-zA-Z0-9_]*/)) do |match|
[307]994# OpenEhr::LOG.info("V_ATTRIBUTE_IDENTIFIER: #{match}")
[283]995# [:V_ATTRIBUTE_IDENTIFIER, match]
996# end)
997# end
998# end
999# end
1000# end # of DADL
[18]1001
[283]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# }
[19]1032
[283]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|
[307]1039# OpenEhr::LOG.info("V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN: #{match}")
[283]1040# [:V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, match]
1041# end
1042# end
1043# end
1044# end
[19]1045
[283]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|
[307]1052# OpenEhr::LOG.info("V_ISO8601_DATE_CONSTRAINT_PATTERN: #{match}")
[283]1053# [:V_ISO8601_DATE_CONSTRAINT_PATTERN, match]
1054# end
1055# end
1056# end
1057# end
[19]1058
[283]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|
[307]1065# OpenEhr::LOG.info("V_ISO8601_TIME_CONSTRAINT_PATTERN: #{match}")
[283]1066# [:V_ISO8601_TIME_CONSTRAINT_PATTERN, match]
1067# end
1068# end
1069# end
1070# end
[19]1071
[283]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|
[307]1079# OpenEhr::LOG.info("V_ISO8601_DURATION_CONSTRAINT_PATTERN: #{match}")
[283]1080# [:V_ISO8601_DURATION_CONSTRAINT_PATTERN, match]
1081# end
1082# end
1083# end
1084# end
[26]1085
[283]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|
[307]1092# OpenEhr::LOG.info("V_C_DOMAIN_TYPE: #{match}")
[283]1093# [:START_V_C_DOMAIN_TYPE_BLOCK, match]
1094# end
1095# end
1096# end
1097# end
[19]1098
[283]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,
[307]1109# OpenEhr::ADL::Scanner::Common::V_ISO8601_DURATION.new,
[283]1110# V_C_DOMAIN_TYPE.new,
1111# V_ISO8601_DURATION_CONSTRAINT_PATTERN.new,
1112# Reserved.new,
[307]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
[283]1123# )
1124# end
1125# end
1126# end
[19]1127
[283]1128# # <CADL::Reserved class>
1129# class Reserved
1130# include Yaparc::Parsable
[19]1131
[283]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|
[307]1139# OpenEhr::LOG.info("Reserved: #{match}")
1140# [OpenEhr::ADL::Scanner::CADL::RESERVED[match], OpenEhr::ADL::Scanner::CADL::RESERVED[match]]
[283]1141# end,
1142# Yaparc::Apply.new(Yaparc::Regex.new(/\A[a-z][a-zA-Z0-9_]*/)) do |match|
[307]1143# OpenEhr::LOG.info("V_ATTRIBUTE_IDENTIFIER: #{match}")
[283]1144# [:V_ATTRIBUTE_IDENTIFIER, match]
1145# end)
1146# end
1147# end
1148# end
[19]1149
[283]1150# end
1151
1152
Note: See TracBrowser for help on using the repository browser.