Ignore:
Timestamp:
Sep 20, 2009, 1:20:48 PM (15 years ago)
Author:
Tatsukawa, Akimichi
Message:

Scanners for ADL parser do not need yaparc library any more

File:
1 edited

Legend:

Unmodified
Added
Removed
  • ruby/trunk/lib/adl_parser/lib/adl_scanner.rb

    r265 r283  
    55require 'am.rb'
    66require 'rm.rb'
     7require 'util.rb'
    78
    89
     
    1011  module ADL
    1112    module Scanner
     13      LOGGER = Logger.new('log/scanner.log')
     14      LOGGER.level = Logger::WARN
    1215
    1316      class Base
     17        attr_accessor :adl_type, :lineno
    1418        def initialize(adl_type, filename, lineno = 1)
    1519          @adl_type = adl_type
     
    2327      end
    2428
    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 
     29      #
     30      # ADLScanner
     31      #
    54532      class ADLScanner < Base
    54633        attr_accessor :adl_type, :lineno, :cadl_scanner, :dadl_scanner, :regex_scanner, :term_constraint_scanner
    54734
    548         @@logger = Logger.new('log/scanner.log')
     35        @@logger = OpenEHR::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')
    54936        RESERVED = {
    55037          'archetype' => :SYM_ARCHETYPE,
     
    56855        def initialize(adl_type, filename, lineno = 1)
    56956          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)}
     57          @in_interval  = false
    57458        end
    57559
     60        #
     61        # ADLScanner#scan
     62        #
    57663        def scan(data)
    577           @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_adl at #{@filename}:#{@lineno}: data = #{data.inspect}")
     64          @@logger.debug("#{__FILE__}:#{__LINE__}: Entering  ADLScanner#scan at #{@filename}:#{@lineno}: data = #{data.inspect}")
    57865          until data.nil?  do
    57966            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
    59867            when :adl
    59968              case data
     
    60372              when /\A[ \t\r\f]+/ #just drop it
    60473                ;
    605               when /\A--.*\n/ # single line comment
     74              when /\A--.*/ # single line comment
    60675                @lineno += 1
    607                 @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: COMMENT = #{$&} at #{@filename}:#{@lineno}")
     76                @@logger.debug("ADLScanner#scan: COMMENT = #{$&} at #{@filename}:#{@lineno}")
    60877                ;
    60978              when /\Adescription/   # description
     
    61180              when /\Adefinition/   # definition
    61281                yield :SYM_DEFINITION, :SYM_DEFINITION
    613                 ###----------/* symbols */ -------------------------------------------------
     82              ###----------/* symbols */ -------------------------------------------------
    61483              when /\A[A-Z][a-zA-Z0-9_]*/
    61584                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
     85              when /\A(\w+)-(\w+)-(\w+)\.(\w+)((?:-\w+)*)\.(v\w+)/   #V_ARCHETYPE_ID
    61886                object_id, rm_originator, rm_name, rm_entity, concept_name, specialisation, version_id = $&, $1, $2, $3, $4, $5, $6
    61987                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, $&
    62188                yield :V_ARCHETYPE_ID, archetype_id
    62289              when /\A[a-z][a-zA-Z0-9_]*/
    623                 #        word = $&.downcase
    62490                word = $&
    62591                if RESERVED[word]
    626                   @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: RESERVED = #{RESERVED[word]} at #{@filename}:#{@lineno}")
     92                  @@logger.debug("ADLScanner#scan: RESERVED = #{RESERVED[word]} at #{@filename}:#{@lineno}")
    62793                  yield RESERVED[word], RESERVED[word]
    62894                elsif #/\A[A-Z][a-zA-Z0-9_]*/
    629                   @@logger.debug("#{__FILE__}:#{__LINE__}: scan_adl: V_ATTRIBUTE_IDENTIFIER = #{$&} at #{@filename}:#{@lineno}")
     95                  @@logger.debug("ADLScanner#scan: V_ATTRIBUTE_IDENTIFIER = #{$&} at #{@filename}:#{@lineno}")
    63096                  yield :V_ATTRIBUTE_IDENTIFIER, $&
    63197                end
     
    637103                yield :SYM_LE, :SYM_LE
    638104              when /\A\</   # <
    639                 if @in_interval                   # @start_block_received = false
     105                if @in_interval
    640106                  yield :SYM_LT, :SYM_LT
    641                 else                              # @start_block_received = true
     107                else
    642108                  @adl_type.push(:dadl)
    643109                  yield :SYM_START_DBLOCK,  $&
     
    653119              when /\A\{/   # {
    654120                @adl_type.push(:cadl)
    655                 @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: entering cADL at #{@filename}:#{@lineno}")
     121                @@logger.debug("ADLScanner#scan: SYM_START_CBLOCK")
    656122                yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
    657123              when /\A\}/   # }
    658124                adl_type = @adl_type.pop
    659125                assert_at(__FILE__,__LINE__){adl_type == :cadl}
    660                 @@logger.debug("#{__FILE__}:#{__LINE__}: scan_cadl: exiting cADL at #{@filename}:#{@lineno}")
     126                @@logger.debug("ADLScanner#scan: SYM_END_CBLOCK")
    661127                yield :SYM_END_CBLOCK, $&
    662128              when /\A\-/   # -
     
    705171                end
    706172                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, $&
     173              when /\A\[([a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+)\]/ #V_QUALIFIED_TERM_CODE_REF form such as [ICD10AM(1998)::F23]
     174                yield :V_QUALIFIED_TERM_CODE_REF, $1
    710175              when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
    711176                yield :V_LOCAL_TERM_CODE_REF, $&
     
    714179              when /\A\]/   # ]
    715180                yield :Right_bracket_code, :Right_bracket_code
    716 
    717181              when /\A"([^"]*)"/m #V_STRING
    718182                yield :V_STRING, $1
     
    730194                yield :V_GENERIC_TYPE_IDENTIFIER, $&
    731195              when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
     196                @@logger.debug("ADLScanner#scan: V_INTEGER = #{$&}")
    732197                yield :V_INTEGER, $&
    733198              when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
     
    742207              end
    743208              data = $' # variable $' receives the string after the match
     209            when :dadl
     210              dadl_scanner = OpenEHR::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
     211              data = dadl_scanner.scan(data) do |sym, val|
     212                yield sym, val
     213              end
     214            when :cadl
     215              cadl_scanner = OpenEHR::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
     216              data = cadl_scanner.scan(data) do |sym, val|
     217                yield sym, val
     218              end
     219            when :regexp
     220              regex_scanner = OpenEHR::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
     221              data = regex_scanner.scan(data) do |sym, val|
     222                yield sym, val
     223              end
     224            when :term_constraint
     225              term_constraint_scanner = OpenEHR::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
     226              data = term_constraint_scanner.scan(data) do |sym, val|
     227                yield sym, val
     228              end
    744229            else
    745230              raise
     
    747232          end
    748233        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
     234      end # of ADLScanner
     235
     236      #
     237      # DADLScanner
     238      #
     239      class DADLScanner < Base
     240        @@logger = OpenEHR::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')
    882241        RESERVED = {
    883242          'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
     
    885244          'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
    886245        }
     246
     247        def initialize(adl_type, filename, lineno = 1)
     248          super(adl_type, filename, lineno)
     249          @in_interval = false
     250          @in_c_domain_type = false
     251        end
     252
    887253        #
    888         # DADL::RootScanner
     254        # DADLScanner#scan
    889255        #
    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                               )
     256        def scan(data)
     257          @@logger.debug("Entering DADLScanner#scan at #{@filename}:#{@lineno}: @adl_type = #{@adl_type.inspect}, data = #{data.inspect}")
     258          until data.nil?  do
     259            @@logger.debug("#{@filename}:#{@lineno}: DADLScanner#scan:loop data = #{data.inspect}")
     260            case @adl_type.last
     261            when :dadl
     262              case data
     263              when /\A\n/ # carriage return
     264                #@@logger.debug("DADLScanner#scan:  carriage return, data = #{data.inspect}")
     265                @lineno += 1
     266                ;
     267              when /\A[ \t\r\f]+/ #just drop it
     268                #@@logger.debug("DADLScanner#scan:  white space, data = #{data.inspect}")
     269                ;
     270              when /\A--.*/ # single line comment
     271#                @lineno += 1
     272                @@logger.debug("DADLScanner#scan: COMMENT = #{$&} at #{@filename}:#{@lineno}")
     273                ;
     274              when /\A[a-z][a-zA-Z0-9_]*/
     275                word = $&.dup
     276                if RESERVED[word.downcase]
     277                  yield RESERVED[word.downcase], RESERVED[word.downcase]
     278                else
     279                  @@logger.debug("DADLScanner#scan: V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}:#{@lineno}")
     280                  yield :V_ATTRIBUTE_IDENTIFIER, word #V_ATTRIBUTE_IDENTIFIER /\A[a-z][a-zA-Z0-9_]*/
     281                end
     282                ###----------/* symbols */ -------------------------------------------------
     283              when /\A\=/   # =
     284                yield :SYM_EQ, :SYM_EQ
     285              when /\A\>\=/   # >=
     286                yield :SYM_GE, :SYM_GE
     287              when /\A\<\=/   # <=
     288                yield :SYM_LE, :SYM_LE
     289              when /\A\</   # <
     290                if @in_interval
     291                  yield :SYM_LT, :SYM_LT
     292                else
     293                  @adl_type.push(:dadl)
     294                  yield :SYM_START_DBLOCK, :SYM_START_DBLOCK
     295                end
     296              when /\A\>/   # >
     297                if @in_interval
     298                  yield :SYM_GT, :SYM_GT
     299                elsif @in_c_domain_type == true
     300                  assert_at(__FILE__,__LINE__){@adl_type.last == :dadl}
     301                  adl_type = @adl_type.pop
     302                  if @adl_type.last == :cadl
     303                    @in_c_domain_type = false
     304                    yield :END_V_C_DOMAIN_TYPE_BLOCK, $&
     305                  else
     306                    yield :SYM_END_DBLOCK, $&
     307                  end
     308                elsif @in_c_domain_type == false
     309                  adl_type = @adl_type.pop
     310                  assert_at(__FILE__,__LINE__){adl_type == :dadl}
     311                  yield :SYM_END_DBLOCK, $&
     312                else
     313                  raise
     314                end
     315              when /\A\-/   # -
     316                yield :Minus_code, :Minus_code
     317              when /\A\+/   # +
     318                yield :Plus_code, :Plus_code
     319              when /\A\*/   # *
     320                yield :Star_code, :Star_code
     321              when /\A\//   # /
     322                yield :Slash_code, :Slash_code
     323              when /\A\^/   # ^
     324                yield :Caret_code, :Caret_code
     325              when /\A\.\.\./   # ...
     326                yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
     327              when /\A\.\./   # ..
     328                yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
     329              when /\A\./   # .
     330                yield :Dot_code, :Dot_code
     331              when /\A\;/   # ;
     332                yield :Semicolon_code, :Semicolon_code
     333              when /\A\,/   # ,
     334                yield :Comma_code, :Comma_code
     335              when /\A\:/   # :
     336                yield :Colon_code, :Colon_code
     337              when /\A\!/   # !
     338                yield :Exclamation_code, :Exclamation_code
     339              when /\A\(/   # (
     340                yield :Left_parenthesis_code, :Left_parenthesis_code
     341              when /\A\)/   # )
     342                yield :Right_parenthesis_code, :Right_parenthesis_code
     343              when /\A\$/   # $
     344                yield :Dollar_code, :Dollar_code
     345              when /\A\?\?/   # ??
     346                yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
     347              when /\A\?/   # ?
     348                yield :Question_mark_code, :Question_mark_code
     349              when /\A\|/   # |
     350                @@logger.debug("DADLScanner#scan: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
     351                if @in_interval
     352                  @in_interval = false
     353                else
     354                  #          @in_interval = false
     355                  @in_interval = true
     356                end
     357                @@logger.debug("DADLScanner#scan: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
     358                yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
     359              when /\A\[([a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+)\]/  #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
     360                yield :V_QUALIFIED_TERM_CODE_REF, $1
     361              when /\A\[/   # [
     362                @@logger.debug("DADLScanner#scan: Left_bracket_code at #{@filename}:#{@lineno}")
     363                yield :Left_bracket_code, :Left_bracket_code
     364              when /\A\]/   # ]
     365                @@logger.debug("DADLScanner#scan: Right_bracket_code at #{@filename}:#{@lineno}")
     366                yield :Right_bracket_code, :Right_bracket_code
     367              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-]-
     368                @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_DATE_TIME")
     369                yield :V_ISO8601_EXTENDED_DATE_TIME, $&
     370              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]
     371                @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_TIME")
     372                yield :V_ISO8601_EXTENDED_TIME, $&
     373              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
     374                @@logger.debug("DADLScanner#scan: V_ISO8601_EXTENDED_DATE, #{$&}")
     375                yield :V_ISO8601_EXTENDED_DATE, $&
     376              when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
     377                yield :V_GENERIC_TYPE_IDENTIFIER, $&
     378              when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
     379                @@logger.debug("DADLScanner#scan: V_STRING, #{$1}")
     380                yield :V_STRING, $1
     381              when /\A"([^"]*)"/m #V_STRING
     382                @@logger.debug("DADLScanner#scan: V_STRING, #{$1}")
     383                yield :V_STRING, $1
     384              when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
     385                @@logger.debug("DADLScanner#scan: V_INTEGER = #{$&}")
     386                yield :V_INTEGER, $&
     387              when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
     388                yield :V_URI, $&
     389              when /\A\S/ #UTF8CHAR
     390                yield :UTF8CHAR, $&
     391              end
     392              data = $' # variable $' receives the string after the match
     393            when :adl
     394              adl_scanner = OpenEHR::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
     395              data = adl_scanner.scan(data) do |sym, val|
     396                yield sym, val
     397              end
     398            when :cadl
     399              cadl_scanner = OpenEHR::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
     400              data = cadl_scanner.scan(data) do |sym, val|
     401                yield sym, val
     402              end
     403            when :regexp
     404              regex_scanner = OpenEHR::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
     405              data = regex_scanner.scan(data) do |sym, val|
     406                yield sym, val
     407              end
     408            when :term_constraint
     409              @@logger.debug("#{__FILE__}:#{__LINE__}: scan_dadl: Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
     410              term_constraint_scanner = OpenEHR::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
     411              data = term_constraint_scanner.scan(data) do |sym, val|
     412                yield sym, val
     413              end
     414            else
     415              raise
    906416            end
    907417          end
    908418        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
     419      end # of DADLScanner
     420
     421
     422
     423      class CADLScanner < Base
     424
     425        @@logger = OpenEHR::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')        #Logger.new('log/scanner.log')
    936426        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]
    939427          'then' => :SYM_THEN, # [Tt][Hh][Ee][Nn]
    940428          'else' => :SYM_ELSE, # [Ee][Ll][Ss][Ee]
     
    951439          'occurrences' => :SYM_OCCURRENCES, # [Oo][Cc][Cc][Uu][Rr][Rr][Ee][Nn][Cc][Ee][Ss]
    952440          'cardinality' => :SYM_CARDINALITY, # [Cc][Aa][Rr][Dd][Ii][Nn][Aa][Ll][Ii][Tt][Yy]
     441          'ordered' => :SYM_ORDERED, # [Oo][Rr][Dd][Ee][Rr][Ee][Dd]
     442          'unordered' => :SYM_UNORDERED, # [Uu][Nn][Oo][Rr][Dd][Ee][Rr][Ee][Dd]
    953443          'unique' => :SYM_UNIQUE, # [Uu][Nn][Ii][Qq][Uu][Ee]
    954444          'matches' => :SYM_MATCHES, # [Mm][Aa][Tt][Cc][Hh][Ee][Ss]
     
    963453        }
    964454
    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
     455        def initialize(adl_type, filename, lineno = 1)
     456          super(adl_type, filename, lineno)
     457          @in_interval = false
     458        end
     459
     460        #
     461        # CADLScanner#scan
     462        #
     463        def scan(data)
     464          @@logger.debug("#{__FILE__}:#{__LINE__}: Entering CADLScanner#scan at #{@filename}:#{@lineno}: data = #{data.inspect}")
     465          until data.nil?  do
     466            @@logger.debug("CADLScanner#scan:  loop data = #{data.inspect}")
     467            case @adl_type.last
     468            when :cadl
     469              case data
     470              when /\A\n/ # carriage return
     471                @lineno += 1
     472                ;
     473                #yield :CR, :CR
     474              when /\A[ \t\r\f]+/ #just drop it
     475                ;
     476              when /\A--.*\n/ # single line comment
     477                @lineno += 1
     478                ;
     479              ###----------/* symbols */ -------------------------------------------------
     480              when /\A\=/   # =
     481                yield :SYM_EQ, :SYM_EQ
     482              when /\A\>=/   # >=
     483                yield :SYM_GE, :SYM_GE
     484              when /\A\<=/   # <=
     485                yield :SYM_LE, :SYM_LE
     486              when /\A\</   # <
     487                if @in_interval
     488                  yield :SYM_LT, :SYM_LT
     489                else
     490                  @adl_type.push(:dadl)
     491                  yield :SYM_START_DBLOCK,  $&
     492                end
     493              when /\A\>/   # >
     494                if @in_interval
     495                  yield :SYM_GT, :SYM_GT
     496                else
     497                  adl_type = @adl_type.pop
     498                  assert_at(__FILE__,__LINE__){adl_type == :dadl}
     499                  yield :SYM_END_DBLOCK, :SYM_END_DBLOCK
     500                end
     501              when /\A\-/   # -
     502                yield :Minus_code, :Minus_code
     503              when /\A\+/   # +
     504                yield :Plus_code, :Plus_code
     505              when /\A\*/   # *
     506                yield :Star_code, :Star_code
     507              when /\A\//   # /
     508                yield :Slash_code, :Slash_code
     509              when /\A\^/   # ^
     510                yield :Caret_code, :Caret_code
     511              when /\A\.\.\./   # ...
     512                yield :SYM_LIST_CONTINUE, :SYM_LIST_CONTINUE
     513              when /\A\.\./   # ..
     514                yield :SYM_ELLIPSIS, :SYM_ELLIPSIS
     515              when /\A\./   # .
     516                yield :Dot_code, :Dot_code
     517              when /\A\;/   # ;
     518                yield :Semicolon_code, :Semicolon_code
     519              when /\A\,/   # ,
     520                yield :Comma_code, :Comma_code
     521              when /\A\:/   # :
     522                yield :Colon_code, :Colon_code
     523              when /\A\!/   # !
     524                yield :Exclamation_code, :Exclamation_code
     525              when /\A\(/   # (
     526                yield :Left_parenthesis_code, :Left_parenthesis_code
     527              when /\A\)/   # )
     528                yield :Right_parenthesis_code, :Right_parenthesis_code
     529              when /\A\{\// #V_REGEXP
     530                if @adl_type.last != :regexp
     531                  @in_regexp = true
     532                  @adl_type.push(:regexp)
     533                  yield :START_REGEXP_BLOCK, :START_REGEXP_BLOCK
     534                else
     535                  raise
     536                end
     537              when /\A\{/   # {
     538                @adl_type.push(:cadl)
     539                @@logger.debug("CADLScanner#scan: entering cADL at #{@filename}:#{@lineno}")
     540                yield :SYM_START_CBLOCK, :SYM_START_CBLOCK
     541              when /\A\}/   # }
     542                adl_type = @adl_type.pop
     543                assert_at(__FILE__,__LINE__){adl_type == :cadl}
     544                @@logger.debug("CADLScanner#scan: exiting cADL at #{@filename}:#{@lineno}")
     545                yield :SYM_END_CBLOCK, :SYM_END_CBLOCK
     546              when /\A\$/   # $
     547                yield :Dollar_code, :Dollar_code
     548              when /\A\?\?/   # ??
     549                yield :SYM_DT_UNKNOWN, :SYM_DT_UNKNOWN
     550              when /\A\?/   # ?
     551                yield :Question_mark_code, :Question_mark_code
     552              when /\A\|/   # |
     553                @@logger.debug("CADLScanner#scan: @in_interval = #{@in_interval} at #{@filename}:#{@lineno}")
     554                if @in_interval
     555                  @in_interval = false
     556                else
     557                  #          @in_interval = false
     558                  @in_interval = true
     559                end
     560                @@logger.debug("CADLScanner#scan: SYM_INTERVAL_DELIM at #{@filename}:#{@lineno}")
     561                yield :SYM_INTERVAL_DELIM, :SYM_INTERVAL_DELIM
     562
     563              when /\A\[([a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+)\]/  #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
     564                yield :V_QUALIFIED_TERM_CODE_REF, $1
     565              when /\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/   #ERR_V_QUALIFIED_TERM_CODE_REF
     566                yield :ERR_V_QUALIFIED_TERM_CODE_REF, $&
     567              when /\A\[([a-zA-Z0-9\(\)\._\-]+)::[ \t\n]*/
     568                @adl_type.push(:term_constraint)
     569                yield :START_TERM_CODE_CONSTRAINT, $1
     570              when /\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/   #V_LOCAL_TERM_CODE_REF
     571                yield :V_LOCAL_TERM_CODE_REF, $&
     572              when /\A\[/   # [
     573                yield :Left_bracket_code, :Left_bracket_code
     574              when /\A\]/   # ]
     575                yield :Right_bracket_code, :Right_bracket_code
     576              when /\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/   #V_GENERIC_TYPE_IDENTIFIER
     577                yield :V_GENERIC_TYPE_IDENTIFIER, $&
     578              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]/
     579                yield :V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, $&
     580              when /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/
     581                yield :V_ISO8601_DATE_CONSTRAINT_PATTERN, $&
     582              when /\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/
     583                yield :V_ISO8601_TIME_CONSTRAINT_PATTERN, $&
     584                #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
     585              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
     586                yield :V_ISO8601_DURATION, $&
     587              when /\AP[yY]?[mM]?[wW]?[dD]?T[hH]?[mM]?[sS]?/   #V_ISO8601_DURATION_CONSTRAINT_PATTERNo
     588                yield :V_ISO8601_DURATION_CONSTRAINT_PATTERN, $&
     589              when /\A[a-z][a-zA-Z0-9_]*/
     590                word = $&.dup
     591                if RESERVED[word.downcase]
     592                  yield RESERVED[word.downcase], RESERVED[word.downcase]
     593                else
     594                  @@logger.debug("CADLScanner#scan: V_ATTRIBUTE_IDENTIFIER = #{word} at #{@filename}:#{@lineno}")
     595                  yield :V_ATTRIBUTE_IDENTIFIER, word #V_ATTRIBUTE_IDENTIFIER /\A[a-z][a-zA-Z0-9_]*/
     596                end
     597              when /\A[A-Z][a-zA-Z0-9_]*/
     598                word = $&.dup
     599                if RESERVED[word.downcase]
     600                  yield RESERVED[word.downcase], RESERVED[word.downcase]
     601                else
     602                  yield :V_TYPE_IDENTIFIER, $&
     603                end
     604              when /\Aa[ct][0-9.]+/   #V_LOCAL_CODE
     605                yield :V_LOCAL_CODE, $&
     606              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-]-
     607                yield :V_ISO8601_EXTENDED_DATE_TIME, $&
     608              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]
     609                yield :V_ISO8601_EXTENDED_TIME, $&
     610              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
     611                yield :V_ISO8601_EXTENDED_DATE, $&
     612              when /\A[0-9]+|[0-9]+[eE][+-]?[0-9]+/   #V_INTEGER
     613                @@logger.debug("CADLScanner#scan: V_INTEGER = #{$&}")
     614                yield :V_INTEGER, $&
     615              when /\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+ /   #V_REAL
     616                yield :V_REAL, $&
     617              when /\A"((?:[^"\\]+|\\.)*)"/ #V_STRING
     618                yield :V_STRING, $1
     619              when /\A"([^"]*)"/m #V_STRING
     620                yield :V_STRING, $1
     621              when /\A[a-z]+:\/\/[^<>|\\{}^~"\[\] ]*/ #V_URI
     622                yield :V_URI, $&
     623              when /\A\S/ #UTF8CHAR
     624                yield :UTF8CHAR, $&
     625              when /\A.+/ #
     626                raise OpenEHR::ADL::Exception::CADLScanner::Base.new, "can't handle #{data.inspect}"
     627              end
     628              data = $' # variable $' receives the string after the match
     629            when :adl
     630              adl_scanner = OpenEHR::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
     631              data = adl_scanner.scan(data) do |sym, val|
     632                yield sym, val
     633              end
     634            when :dadl
     635              dadl_scanner = OpenEHR::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
     636              data = dadl_scanner.scan(data) do |sym, val|
     637                yield sym, val
     638              end
     639            when :regexp
     640              regex_scanner = OpenEHR::ADL::Scanner::RegexScanner.new(@adl_type, @filename, @lineno)
     641              data = regex_scanner.scan(data) do |sym, val|
     642                yield sym, val
     643              end
     644            when :term_constraint
     645              @@logger.debug("Entering scan_term_constraint at #{@filename}:#{@lineno}: data = #{data.inspect}")
     646              term_constraint_scanner = OpenEHR::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
     647              data = term_constraint_scanner.scan(data) do |sym, val|
     648                yield sym, val
     649              end
     650            else
     651              raise OpenEHR::ADL::Exception::CADLScanner.new, "unexpected adl_type: #{@adl_type.last}"
     652            end
     653          end # of until
     654        end
     655      end # of CADLScanner
     656
     657
     658      #
     659      # RegexScanner
     660      #
     661      class RegexScanner < Base
     662
     663        @@logger = OpenEHR::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')        #Logger.new('log/scanner.log')
     664       
     665        def initialize(adl_type, filename, lineno = 1)
     666          super(adl_type, filename, lineno)
     667        end
     668
     669        def scan(data)
     670          @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_regexp at #{@filename}:#{@lineno}: data = #{data.inspect}")
     671          until data.nil?  do
     672            case @adl_type.last
     673            when :regexp
     674              case data
     675              when /\A\/\}/ #V_REGEXP
     676                if @adl_type.last == :regexp
     677                  @in_regexp = false
     678                  @adl_type.pop
     679                  yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
     680                else
     681                  raise
     682                end
     683              when /\A(.*)(\/\})/ #V_REGEXP
     684                yield :REGEXP_BODY, $1
     685                if @adl_type.last == :regexp
     686                  @in_regexp = false
     687                  @adl_type.pop
     688                  yield :END_REGEXP_BLOCK, :END_REGEXP_BLOCK
     689                else
     690                  raise
     691                end
     692              else
     693                raise data
     694              end
     695              data = $' # variable $' receives the string after the match
     696            when :adl
     697              adl_scanner = OpenEHR::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
     698              data = adl_scanner.scan(data) do |sym, val|
     699                yield sym, val
     700              end
     701            when :dadl
     702              dadl_scanner = OpenEHR::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
     703              data = dadl_scanner.scan(data) do |sym, val|
     704                yield sym, val
     705              end
     706            when :cadl
     707              cadl_scanner = OpenEHR::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
     708              data = cadl_scanner.scan(data) do |sym, val|
     709                yield sym, val
     710              end
     711            when :term_constraint
     712              #@@logger.debug("#{__FILE__}:#{__LINE__}: scan_regexp: Entering scan_term_constraint at #{@filename}:#{@lineno}")
     713              term_constraint_scanner = OpenEHR::ADL::Scanner::TermConstraintScanner.new(@adl_type, @filename, @lineno)
     714              data = term_constraint_scanner.scan(data) do |sym, val|
     715                yield sym, val
     716              end
     717            else
     718              raise
    974719            end
    975720          end
    976721        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
     722      end # of RegexScanner
     723
     724      #
     725      # TermConstraintScanner
     726      #
     727      class TermConstraintScanner < Base
     728        @@logger = OpenEHR::ADL::Scanner::LOGGER #Logger.new('log/scanner.log')        #Logger.new('log/scanner.log')
     729        def initialize(adl_type, filename, lineno = 1)
     730          super(adl_type, filename, lineno)
     731        end
     732
     733        def scan(data)
     734          @@logger.debug("#{__FILE__}:#{__LINE__}: Entering scan_term_constraint")
     735          until data.nil?  do
     736            case @adl_type.last
     737            when :term_constraint
     738              case data
     739              when /\A\n/ # carriage return
     740                @lineno += 1
     741                ;
     742              when /\A[ \t\r\f]+/ #just drop it
     743                ;
     744              when /\A--.*$/ # single line comment
     745                @lineno += 1
     746                @@logger.debug("#{__FILE__}:#{__LINE__}: scan_term_constraint: COMMENT = #{$&} at #{@filename}:#{@lineno}")
     747                ;
     748              when /\A([a-zA-Z0-9\._\-])+[ \t]*,/ # match any line, with ',' termination
     749                yield :TERM_CODE, $1
     750              when /\A([a-zA-Z0-9\._\-])+[ \t]*;/ # match second last line with ';' termination (assumed value)
     751                yield :TERM_CODE, $1
     752              when /\A([a-zA-Z0-9\._\-])*[ \t]*\]/ # match final line, terminating in ']'
     753                adl_type = @adl_type.pop
     754                assert_at(__FILE__,__LINE__){adl_type == :term_constraint}
     755                yield :END_TERM_CODE_CONSTRAINT, $1
     756              else
     757                raise "data = #{data}"
     758              end
     759              data = $' # variable $' receives the string after the match
     760            when :adl
     761              adl_scanner = OpenEHR::ADL::Scanner::ADLScanner.new(@adl_type, @filename, @lineno)
     762              data = adl_scanner.scan(data) do |sym, val|
     763                yield sym, val
     764              end
     765            when :dadl
     766              dadl_scanner = OpenEHR::ADL::Scanner::DADLScanner.new(@adl_type, @filename, @lineno)
     767              data = dadl_scanner.scan(data) do |sym, val|
     768                yield sym, val
     769              end
     770            when :cadl
     771              cadl_scanner = OpenEHR::ADL::Scanner::CADLScanner.new(@adl_type, @filename, @lineno)
     772              data = cadl_scanner.scan(data) do |sym, val|
     773                yield sym, val
     774              end
     775            else
     776              raise
    987777            end
    988778          end
    989779        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
     780      end # of TermConstraintScanner
     781
    1083782    end
    1084783  end
    1085784end
     785
     786__END__
     787
     788
     789
     790#       module Common
     791#         class START_TERM_CODE_CONSTRAINT
     792#           include Yaparc::Parsable
     793#           def initialize
     794#             @parser = lambda do |input|
     795#               Yaparc::Apply.new(Yaparc::Regex.new(/[ \t\n]*\[([a-zA-Z0-9\(\)\._\-]+)::[ \t\n]*/)) do |match|
     796#                 OpenEHR::LOG.info("START_TERM_CODE_CONSTRAINT: #{match}")
     797#                 [:START_TERM_CODE_CONSTRAINT, match]
     798#               end
     799#             end
     800#           end
     801#         end
     802
     803#         # /\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/  #V_QUALIFIED_TERM_CODE_REF form [ICD10AM(1998)::F23]
     804#         class V_QUALIFIED_TERM_CODE_REF
     805#           include Yaparc::Parsable
     806#           def initialize
     807#             @parser = lambda do |input|
     808#               Yaparc::Apply.new(Yaparc::Regex.new(/\A\[[a-zA-Z0-9()\._-]+::[a-zA-Z0-9\._-]+\]/)) do |match|
     809#                 OpenEHR::LOG.info("V_QUALIFIED_TERM_CODE_REF: #{match}")
     810#                 [:V_QUALIFIED_TERM_CODE_REF, match]
     811#               end
     812#             end
     813#           end
     814#         end
     815       
     816#         class V_LOCAL_TERM_CODE_REF
     817#           include Yaparc::Parsable
     818#           def initialize
     819#             @parser = lambda do |input|
     820#               Yaparc::Apply.new(Yaparc::Regex.new(/\A\[[a-zA-Z0-9][a-zA-Z0-9._\-]*\]/)) do |match|
     821#                 OpenEHR::LOG.info("V_TERM_CODE_REF: #{match}")
     822#                 [:V_LOCAL_TERM_CODE_REF, match]
     823#               end
     824#             end
     825#           end
     826#         end
     827
     828#         class ERR_V_QUALIFIED_TERM_CODE_REF
     829#           include Yaparc::Parsable
     830#           def initialize
     831#             @parser = lambda do |input|
     832#               Yaparc::Apply.new(Yaparc::Regex.new(/\A\[[a-zA-Z0-9._\- ]+::[a-zA-Z0-9._\- ]+\]/)) do |match|
     833#                 OpenEHR::LOG.info("ERR_V_QUALIFIED_TERM_CODE_REF: #{match}")
     834#                 [:ERR_V_QUALIFIED_TERM_CODE_REF, match]
     835#               end
     836#             end
     837#           end
     838#         end
     839
     840#         class V_TYPE_IDENTIFIER
     841#           include Yaparc::Parsable
     842#           def initialize
     843#             @parser = lambda do |input|
     844#               Yaparc::Apply.new(Yaparc::Regex.new(/\A[A-Z][a-zA-Z0-9_]*/)) do |match|
     845#                 OpenEHR::LOG.info("V_TYPE_IDENTIFIER: #{match}")
     846#                 [:V_TYPE_IDENTIFIER, match]
     847#               end
     848#             end
     849#           end
     850#         end
     851
     852#         class V_GENERIC_TYPE_IDENTIFIER
     853#           include Yaparc::Parsable
     854#           def initialize
     855#             @parser = lambda do |input|
     856#               Yaparc::Apply.new(Yaparc::Regex.new(/\A[A-Z][a-zA-Z0-9_]*<[a-zA-Z0-9,_<>]+>/)) do |match|
     857#                 OpenEHR::LOG.info("V_GENERIC_TYPE_IDENTIFIER: #{match}")
     858#                 [:V_GENERIC_TYPE_IDENTIFIER, match]
     859#               end
     860#             end
     861#           end
     862#         end
     863
     864
     865#         class V_LOCAL_CODE
     866#           include Yaparc::Parsable
     867#           def initialize
     868#             @parser = lambda do |input|
     869#               Yaparc::Apply.new(Yaparc::Regex.new(/\Aa[ct][0-9.]+/)) do |match|
     870#                 OpenEHR::LOG.info("V_LOCAL_CODE: #{match}")
     871#                 [:V_LOCAL_CODE, match]
     872#               end
     873#             end
     874#           end
     875#         end
     876
     877#         class V_STRING
     878#           include Yaparc::Parsable
     879#           def initialize
     880#             @parser = lambda do |input|
     881#               Yaparc::Apply.new(Yaparc::Regex.new(/\A"([^"]*)"/m)) do |match|
     882#                 OpenEHR::LOG.info("V_STRING: #{match}")
     883#                 [:V_STRING, match]
     884#               end
     885#             end
     886#           end
     887#         end
     888
     889#         class V_REAL
     890#           include Yaparc::Parsable
     891#           def initialize
     892#             @parser = lambda do |input|
     893#               Yaparc::Apply.new(Yaparc::Regex.new(/\A[0-9]+\.[0-9]+|[0-9]+\.[0-9]+[eE][+-]?[0-9]+/)) do |match|
     894#                 OpenEHR::LOG.info("V_REAL: #{match}")
     895#                 [:V_REAL, match]
     896#               end
     897#             end
     898#           end
     899#         end
     900
     901#         #V_ISO8601_DURATION PnYnMnWnDTnnHnnMnnS
     902#         class V_ISO8601_DURATION
     903#           include Yaparc::Parsable
     904#           def initialize
     905#             @parser = lambda do |input|
     906#               Yaparc::Apply.new(
     907#                                 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])?/),
     908#                                                 Yaparc::Regex.new(/\AP([0-9]+|[yY])?([0-9]+|[mM])?([0-9]+|[wW])?([0-9]+|[dD])?/))) do |match|
     909#                 OpenEHR::LOG.info("V_ISO8601_DURATION: #{match}")
     910#                 [:V_ISO8601_DURATION, match]
     911#               end
     912#             end
     913#           end
     914#         end
     915
     916#       end # of Common
     917
     918#       module DADL
     919#         # c.f. http://www.openehr.org/svn/ref_impl_eiffel/TRUNK/components/adl_parser/src/syntax/adl/parser/adl_scanner.l
     920#         RESERVED = {
     921#           'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
     922#           'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
     923#           'infinity' => :SYM_INFINITY # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
     924#         }
     925#         #
     926#         # DADL::RootScanner
     927#         #
     928#         class RootScanner
     929#           include Yaparc::Parsable
     930#           def initialize
     931#             @parser = lambda do |input|
     932#               Yaparc::Alt.new(Reserved.new,
     933#                               OpenEHR::ADL::Scanner::Common::V_QUALIFIED_TERM_CODE_REF.new,
     934#                               OpenEHR::ADL::Scanner::Common::V_LOCAL_TERM_CODE_REF.new,
     935#                               OpenEHR::ADL::Scanner::Common::ERR_V_QUALIFIED_TERM_CODE_REF.new,
     936#                               OpenEHR::ADL::Scanner::Common::V_TYPE_IDENTIFIER.new,
     937#                               OpenEHR::ADL::Scanner::Common::V_GENERIC_TYPE_IDENTIFIER.new,
     938#                               OpenEHR::ADL::Scanner::Common::V_STRING.new,
     939#                               OpenEHR::ADL::Scanner::Common::V_LOCAL_CODE.new,
     940#                               OpenEHR::ADL::Scanner::Common::V_REAL.new,
     941#                               OpenEHR::ADL::Scanner::Common::V_ISO8601_DURATION.new#,
     942#                               #OpenEHR::ADL::Scanner::Common::START_TERM_CODE_CONSTRAINT.new
     943#                               )
     944#             end
     945#           end
     946#         end
     947
     948#         #  <DADL::Reserved class>
     949#         class Reserved
     950#           include Yaparc::Parsable
     951         
     952#           def initialize
     953#             @parser = lambda do |input|
     954#               reserved_parsers = OpenEHR::ADL::Scanner::DADL::RESERVED.map do |keyword|
     955#                 Yaparc::Tokenize.new(
     956#                                      Yaparc::Literal.new(keyword[0],false)
     957#                                      )
     958#               end
     959#               Yaparc::Alt.new(Yaparc::Apply.new(Yaparc::Alt.new(*reserved_parsers)) do |match|
     960#                                 OpenEHR::LOG.info("Reserved: #{match}")
     961#                                 [OpenEHR::ADL::Scanner::DADL::RESERVED[match], OpenEHR::ADL::Scanner::DADL::RESERVED[match]]
     962#                               end,
     963#                               Yaparc::Apply.new(Yaparc::Regex.new(/\A[a-z][a-zA-Z0-9_]*/)) do |match|
     964#                                 OpenEHR::LOG.info("V_ATTRIBUTE_IDENTIFIER: #{match}")
     965#                                 [:V_ATTRIBUTE_IDENTIFIER, match]
     966#                               end)
     967#             end
     968#           end
     969#         end
     970#       end # of DADL
     971
     972#       module CADL
     973#         # c.f. http://www.openehr.org/svn/ref_impl_eiffel/TRUNK/components/adl_parser/src/syntax/cadl/parser/cadl_scanner.l
     974#         RESERVED = {
     975#           'ordered' => :SYM_ORDERED, # [Oo][Rr][Dd][Ee][Rr][Ee][Dd]
     976#           'unordered' => :SYM_UNORDERED, # [Uu][Nn][Oo][Rr][Dd][Ee][Rr][Ee][Dd]
     977#           'then' => :SYM_THEN, # [Tt][Hh][Ee][Nn]
     978#           'else' => :SYM_ELSE, # [Ee][Ll][Ss][Ee]
     979#           'and' => :SYM_AND, # [Aa][Nn][Dd]
     980#           'or' => :SYM_OR, # [Oo][Rr]
     981#           'xor' => :SYM_XOR, # [Xx][Oo][Rr]
     982#           'not' => :SYM_NOT, # [Nn][Oo][Tt]
     983#           'implies' => :SYM_IMPLIES, # [Ii][Mm][Pp][Ll][Ii][Ee][Ss]
     984#           'true' => :SYM_TRUE, #[Tt][Rr][Uu][Ee] -- -> SYM_TRUE
     985#           'false' => :SYM_FALSE, # [Ff][Aa][Ll][Ss][Ee] -- -> SYM_FALSE
     986#           'forall' => :SYM_FORALL, # [Ff][Oo][Rr][_][Aa][Ll][Ll]
     987#           'exists' => :SYM_EXISTS, # [Ee][Xx][Ii][Ss][Tt][Ss]
     988#           'existence' => :SYM_EXISTENCE, # [Ee][Xx][Iu][Ss][Tt][Ee][Nn][Cc][Ee]
     989#           'occurrences' => :SYM_OCCURRENCES, # [Oo][Cc][Cc][Uu][Rr][Rr][Ee][Nn][Cc][Ee][Ss]
     990#           'cardinality' => :SYM_CARDINALITY, # [Cc][Aa][Rr][Dd][Ii][Nn][Aa][Ll][Ii][Tt][Yy]
     991#           'unique' => :SYM_UNIQUE, # [Uu][Nn][Ii][Qq][Uu][Ee]
     992#           'matches' => :SYM_MATCHES, # [Mm][Aa][Tt][Cc][Hh][Ee][Ss]
     993#           'is_in' => :SYM_MATCHES, # [Ii][Ss][_][Ii][Nn]
     994#           'invariant' => :SYM_INVARIANT, # [Ii][Nn][Vv][Aa][Rr][Ii][Aa][Nn][Tt]
     995#           'infinity' => :SYM_INFINITY, # [Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] -- -> SYM_INFINITY
     996#           'use_node' => :SYM_USE_NODE, # [Uu][Ss][Ee][_][Nn][Oo][Dd][Ee]
     997#           'use_archetype' => :SYM_ALLOW_ARCHETYPE, # [Uu][Ss][Ee][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
     998#           'allow_archetype' => :SYM_ALLOW_ARCHETYPE, # [Aa][Ll][Ll][Oo][Ww][_][Aa][Rr][Cc][Hh][Ee][Tt][Yy][Pp][Ee]
     999#           'include' => :SYM_INCLUDE, # [Ii][Nn][Cc][Ll][Uu][Dd][Ee]
     1000#           'exclude' => :SYM_EXCLUDE # [Ee][Xx][Cc][Ll][Uu][Dd][Ee]
     1001#         }
     1002
     1003#         #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]/
     1004#         class V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN
     1005#           include Yaparc::Parsable
     1006#           def initialize
     1007#             @parser = lambda do |input|
     1008#               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|
     1009#                 OpenEHR::LOG.info("V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN: #{match}")
     1010#                 [:V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN, match]
     1011#               end
     1012#             end
     1013#           end
     1014#         end
     1015
     1016#         #V_ISO8601_DATE_CONSTRAINT_PATTERN  /\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/
     1017#         class V_ISO8601_DATE_CONSTRAINT_PATTERN
     1018#           include Yaparc::Parsable
     1019#           def initialize
     1020#             @parser = lambda do |input|
     1021#               Yaparc::Apply.new(Yaparc::Regex.new(/\A[yY][yY][yY][yY]-[mM?X][mM?X]-[dD?X][dD?X]/)) do |match|
     1022#                 OpenEHR::LOG.info("V_ISO8601_DATE_CONSTRAINT_PATTERN: #{match}")
     1023#                 [:V_ISO8601_DATE_CONSTRAINT_PATTERN, match]
     1024#               end
     1025#             end
     1026#           end
     1027#         end
     1028
     1029#         #V_ISO8601_TIME_CONSTRAINT_PATTERN /\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/
     1030#         class V_ISO8601_TIME_CONSTRAINT_PATTERN
     1031#           include Yaparc::Parsable
     1032#           def initialize
     1033#             @parser = lambda do |input|
     1034#               Yaparc::Apply.new(Yaparc::Regex.new(/\A[hH][hH]:[mM?X][mM?X]:[sS?X][sS?X]/)) do |match|
     1035#                 OpenEHR::LOG.info("V_ISO8601_TIME_CONSTRAINT_PATTERN: #{match}")
     1036#                 [:V_ISO8601_TIME_CONSTRAINT_PATTERN, match]
     1037#               end
     1038#             end
     1039#           end
     1040#         end
     1041
     1042#         #V_ISO8601_DURATION_CONSTRAINT_PATTERN
     1043#         class V_ISO8601_DURATION_CONSTRAINT_PATTERN
     1044#           include Yaparc::Parsable
     1045#           def initialize
     1046#             @parser = lambda do |input|
     1047#               Yaparc::Apply.new(Yaparc::Alt.new(Yaparc::Regex.new(/\AP[yY]?[mM]?[wW]?[dD]?T[hH]?[mM]?[sS]?/),
     1048#                                                 Yaparc::Regex.new(/\AP[yY]?[mM]?[wW]?[dD]?/))) do |match|
     1049#                 OpenEHR::LOG.info("V_ISO8601_DURATION_CONSTRAINT_PATTERN: #{match}")
     1050#                 [:V_ISO8601_DURATION_CONSTRAINT_PATTERN, match]
     1051#               end
     1052#             end
     1053#           end
     1054#         end
     1055
     1056#         #V_C_DOMAIN_TYPE /\A[A-Z][a-zA-Z0-9_]*[ \n]*\</
     1057#         class V_C_DOMAIN_TYPE
     1058#           include Yaparc::Parsable
     1059#           def initialize
     1060#             @parser = lambda do |input|
     1061#               Yaparc::Apply.new(Yaparc::Regex.new(/\A[A-Z][a-zA-Z0-9_]*[ \n]*\</)) do |match|
     1062#                 OpenEHR::LOG.info("V_C_DOMAIN_TYPE: #{match}")
     1063#                 [:START_V_C_DOMAIN_TYPE_BLOCK, match]
     1064#               end
     1065#             end
     1066#           end
     1067#         end
     1068
     1069#         #
     1070#         # CADL::RootScanner
     1071#         #
     1072#         class RootScanner
     1073#           include Yaparc::Parsable
     1074#           def initialize
     1075#             @parser = lambda do |input|
     1076#               Yaparc::Alt.new(V_ISO8601_DATE_TIME_CONSTRAINT_PATTERN.new,
     1077#                               V_ISO8601_DATE_CONSTRAINT_PATTERN.new,
     1078#                               V_ISO8601_TIME_CONSTRAINT_PATTERN.new,
     1079#                               OpenEHR::ADL::Scanner::Common::V_ISO8601_DURATION.new,
     1080#                               V_C_DOMAIN_TYPE.new,
     1081#                               V_ISO8601_DURATION_CONSTRAINT_PATTERN.new,
     1082#                               Reserved.new,
     1083#                               OpenEHR::ADL::Scanner::Common::V_QUALIFIED_TERM_CODE_REF.new,
     1084#                               OpenEHR::ADL::Scanner::Common::V_LOCAL_TERM_CODE_REF.new,
     1085#                               OpenEHR::ADL::Scanner::Common::ERR_V_QUALIFIED_TERM_CODE_REF.new,
     1086#                               OpenEHR::ADL::Scanner::Common::V_TYPE_IDENTIFIER.new,
     1087#                               OpenEHR::ADL::Scanner::Common::V_GENERIC_TYPE_IDENTIFIER.new,
     1088#                               OpenEHR::ADL::Scanner::Common::V_STRING.new,
     1089#                               OpenEHR::ADL::Scanner::Common::V_LOCAL_CODE.new,
     1090#                               OpenEHR::ADL::Scanner::Common::V_REAL.new,
     1091#                               OpenEHR::ADL::Scanner::Common::V_ISO8601_DURATION.new#,
     1092#                               #OpenEHR::ADL::Scanner::Common::START_TERM_CODE_CONSTRAINT.new
     1093#                               )
     1094#             end
     1095#           end
     1096#         end
     1097
     1098#         # <CADL::Reserved class>
     1099#         class Reserved
     1100#           include Yaparc::Parsable
     1101         
     1102#           def initialize
     1103#             @parser = lambda do |input|
     1104#               orderd_reserved = RESERVED.keys.sort{|x,y| y.length <=> x.length  }
     1105#               reserved_parsers = orderd_reserved.map do |keyword|
     1106#                 Yaparc::Literal.new(keyword,false)
     1107#               end
     1108#               Yaparc::Alt.new(Yaparc::Apply.new(Yaparc::Alt.new(*reserved_parsers)) do |match|
     1109#                                 OpenEHR::LOG.info("Reserved: #{match}")
     1110#                                 [OpenEHR::ADL::Scanner::CADL::RESERVED[match], OpenEHR::ADL::Scanner::CADL::RESERVED[match]]
     1111#                               end,
     1112#                               Yaparc::Apply.new(Yaparc::Regex.new(/\A[a-z][a-zA-Z0-9_]*/)) do |match|
     1113#                                 OpenEHR::LOG.info("V_ATTRIBUTE_IDENTIFIER: #{match}")
     1114#                                 [:V_ATTRIBUTE_IDENTIFIER, match]
     1115#                               end)
     1116#             end
     1117#           end
     1118#         end
     1119
     1120#       end
     1121
     1122
Note: See TracChangeset for help on using the changeset viewer.