class Bismas::Parser

  1. Each record is terminated by 0x0D 0x0A (CHARS[:newline]).

  2. Each record starts with 0x01 (CHARS[:rs]) or, if it’s a deleted record, with 0xFF (CHARS[:deleted]).

  3. Each field is terminated by 0x00 (CHARS[:fs]).

  4. Each field starts with the category “number”, a run of category_length characters except 0x00, 0x01, 0xDB or 0xFF; trailing space is stripped.

  5. The remaining characters of a field form the category content; trailing padding 0xDB (CHARS[:padding]) is stripped.

To quote the BISMAS handbook: “Konkret wird bei BISMAS jeder Datensatz durch ASCII(1) eingeleitet. Es folgt die erste Kategorienummer mit dem Kategorieinhalt. Abgeschlossen wird jede Kategorie mit ASCII(0), danach folgt die nächste Kategorienummer und -inhalt usw. Der gesamte Datensatz wird mit ASCII (13)(10) abgeschlossen.”

Public Class Methods

new(options = {}) click to toggle source
   # File lib/bismas/parser.rb
79 def initialize(options = {})
80   @regex = Bismas.regex(options)
81 
82   @strict, @silent = options.values_at(:strict, :silent)
83 end
parse(io, options = {}, &block) click to toggle source
   # File lib/bismas/parser.rb
74 def self.parse(io, options = {}, &block)
75   klass = options[:legacy] ? Legacy : self
76   klass.new(options).parse(io, &block)
77 end

Public Instance Methods

parse(io, &block) click to toggle source
   # File lib/bismas/parser.rb
85 def parse(io, &block)
86   @input = StringScanner.new('')
87 
88   io.each { |input|
89     @input << input
90 
91     parse_record(&block) while @input.check_until(@regex[:newline])
92     @input.string = @input.string.byteslice(@input.pos..-1)
93   }
94 
95   error('Unexpected data') unless @input.eos?
96 
97   self
98 end
parse_field() { |k, v| ... } click to toggle source
    # File lib/bismas/parser.rb
115 def parse_field
116   k = match(:category, 0) and k.rstrip!
117 
118   v = match(:field, 1) or error(k ?
119     "Unclosed field `#{k}'" : 'Unexpected data', :rest)
120 
121   k ? block_given? ? yield(k, v) : [k, v] :
122     v.empty? ? nil : error('Malformed field', :field)
123 end
parse_record() { |r| ... } click to toggle source
    # File lib/bismas/parser.rb
100 def parse_record
101   if match(:deleted)
102     match(:skip_line)
103     return
104   elsif !match_record
105     error('Malformed record', :line)
106     return
107   end
108 
109   r = Hash.new { |h, k| h[k] = [] }
110   parse_field  { |k, v| r[k] << v } until match(:newline)
111 
112   block_given? ? yield(r) : r
113 end

Private Instance Methods

error(message, skip = nil) click to toggle source
    # File lib/bismas/parser.rb
136 def error(message, skip = nil)
137   err = parse_error(message)
138   raise err unless skip && !@strict
139 
140   warn err.to_s unless @silent
141   match(:"skip_#{skip}")
142   nil
143 end
match(key, index = nil) click to toggle source
    # File lib/bismas/parser.rb
127 def match(key, index = nil)
128   res = @input.skip(@regex.fetch(key))
129   res && index ? @input[index] : res
130 end
match_record() click to toggle source
    # File lib/bismas/parser.rb
132 def match_record
133   match(:rs)
134 end
parse_error(message) click to toggle source
    # File lib/bismas/parser.rb
145 def parse_error(message)
146   ParseError.new(@input, message)
147 end