oddb2xml 2.7.1 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/.standard.yml +2 -0
  4. data/Gemfile +3 -3
  5. data/History.txt +8 -0
  6. data/README.md +1 -1
  7. data/Rakefile +24 -23
  8. data/bin/check_artikelstamm +11 -11
  9. data/bin/compare_v5 +23 -23
  10. data/bin/oddb2xml +14 -13
  11. data/lib/oddb2xml.rb +1 -1
  12. data/lib/oddb2xml/builder.rb +1070 -1038
  13. data/lib/oddb2xml/calc.rb +232 -233
  14. data/lib/oddb2xml/chapter_70_hack.rb +38 -32
  15. data/lib/oddb2xml/cli.rb +252 -236
  16. data/lib/oddb2xml/compare.rb +70 -59
  17. data/lib/oddb2xml/compositions_syntax.rb +448 -430
  18. data/lib/oddb2xml/compressor.rb +20 -20
  19. data/lib/oddb2xml/downloader.rb +153 -127
  20. data/lib/oddb2xml/extractor.rb +302 -289
  21. data/lib/oddb2xml/options.rb +34 -35
  22. data/lib/oddb2xml/parslet_compositions.rb +263 -269
  23. data/lib/oddb2xml/semantic_check.rb +39 -33
  24. data/lib/oddb2xml/util.rb +163 -163
  25. data/lib/oddb2xml/version.rb +1 -1
  26. data/lib/oddb2xml/xml_definitions.rb +32 -33
  27. data/oddb2xml.gemspec +31 -32
  28. data/spec/artikelstamm_spec.rb +111 -110
  29. data/spec/builder_spec.rb +489 -505
  30. data/spec/calc_spec.rb +552 -593
  31. data/spec/check_artikelstamm_spec.rb +26 -26
  32. data/spec/cli_spec.rb +173 -174
  33. data/spec/compare_spec.rb +9 -11
  34. data/spec/composition_syntax_spec.rb +390 -409
  35. data/spec/compressor_spec.rb +48 -48
  36. data/spec/data/transfer.dat +1 -0
  37. data/spec/data_helper.rb +47 -49
  38. data/spec/downloader_spec.rb +247 -260
  39. data/spec/extractor_spec.rb +171 -159
  40. data/spec/galenic_spec.rb +233 -256
  41. data/spec/options_spec.rb +116 -119
  42. data/spec/parslet_spec.rb +833 -861
  43. data/spec/spec_helper.rb +154 -153
  44. data/test_options.rb +39 -42
  45. data/tools/win_fetch_cacerts.rb +2 -3
  46. metadata +19 -3
@@ -1,22 +1,22 @@
1
- # encoding: utf-8
2
- require 'xmlsimple'
1
+ require "xmlsimple"
3
2
 
4
3
  module Oddb2xml
5
4
  def self.log_timestamp(msg)
6
5
  full_msg = "#{Time.now.strftime("%H:%M:%S")}: #{msg}"
7
6
  puts full_msg
8
- STDOUT.flush
7
+ $stdout.flush
9
8
  full_msg
10
9
  end
10
+
11
11
  class StammXML
12
12
  V3_NAME_REG = /_([N,P])_/
13
13
  attr_accessor :components
14
14
  attr_reader :keys, :sub_key_names, :filename, :basename, :version, :hash
15
- def initialize(filename, components = ['ITEMS'])
15
+ def initialize(filename, components = ["ITEMS"])
16
16
  raise "File #{filename} must exist" unless File.exist?(filename)
17
17
  @filename = filename
18
18
  @basename = File.basename(filename)
19
- @version = V3_NAME_REG.match(filename) ? 3 : 5
19
+ @version = V3_NAME_REG.match(filename) ? 3 : 5
20
20
  @components = components
21
21
  if @version == 5
22
22
  @hash = load_file(@filename)
@@ -24,41 +24,47 @@ module Oddb2xml
24
24
  raise "Unsupported version #{@version}"
25
25
  end
26
26
  end
27
+
27
28
  def self.get_component_key_name(component_name)
28
- return 'LIMNAMEBAG' if /LIMITATION/i.match(component_name)
29
- return 'PRODNO' if /PRODUCT/i.match(component_name)
30
- return 'GTIN' if /ITEM/i.match(component_name)
31
- raise "Cannot determine keyname for component #{component_name}"
29
+ return "LIMNAMEBAG" if /LIMITATION/i.match?(component_name)
30
+ return "PRODNO" if /PRODUCT/i.match?(component_name)
31
+ return "GTIN" if /ITEM/i.match?(component_name)
32
+ raise "Cannot determine keyname for component #{component_name}"
32
33
  end
34
+
33
35
  def get_limitation_from_v5(item)
34
- get_item('PRODUCTS', item['PRODNO'].first.to_i)['LIMNAMEBAG'] ? ['true'] : nil
36
+ get_item("PRODUCTS", item["PRODNO"].first.to_i)["LIMNAMEBAG"] ? ["true"] : nil
35
37
  end
38
+
36
39
  def get_field_from_v5_product(item, field_name)
37
- get_item('PRODUCTS', item['PRODNO'].first.to_i)[field_name]
40
+ get_item("PRODUCTS", item["PRODNO"].first.to_i)[field_name]
38
41
  end
42
+
39
43
  def get_items(component_name)
40
44
  if @version == 3
41
- items = @hash[component_name]
45
+ @hash[component_name]
42
46
  else
43
- items = @hash[component_name].first.values.first
47
+ @hash[component_name].first.values.first
44
48
  end
45
- items
46
49
  end
50
+
47
51
  def get_item(component_name, id)
48
52
  keyname = StammXML.get_component_key_name(component_name)
49
- get_items(component_name).find{|item| item[keyname].first.to_i == id}
53
+ get_items(component_name).find { |item| item[keyname].first.to_i == id }
50
54
  end
55
+
51
56
  def load_file(name)
52
- Oddb2xml.log_timestamp "Reading #{name} #{(File.size(name)/1024/1024).to_i} MB. This may take some time"
57
+ Oddb2xml.log_timestamp "Reading #{name} #{(File.size(name) / 1024 / 1024).to_i} MB. This may take some time"
53
58
  XmlSimple.xml_in(IO.read(name))
54
59
  end
55
60
  end
61
+
56
62
  class CompareV5
57
63
  DEFAULTS = {
58
- :components => ["PRODUCTS", "LIMITATIONS", "ITEMS",],
59
- :fields_to_ignore => ['COMP', 'DOSAGE_FORMF', 'MEASUREF'],
60
- :fields_as_floats => [ 'PEXT', 'PEXF', 'PPUB' ],
61
- :min_diff_for_floats => 0.01,
64
+ components: ["PRODUCTS", "LIMITATIONS", "ITEMS"],
65
+ fields_to_ignore: ["COMP", "DOSAGE_FORMF", "MEASUREF"],
66
+ fields_as_floats: ["PEXT", "PEXF", "PPUB"],
67
+ min_diff_for_floats: 0.01
62
68
  }
63
69
  def initialize(left, right, options = DEFAULTS.clone)
64
70
  @options = options
@@ -68,37 +74,38 @@ module Oddb2xml
68
74
  @occurrences = {}
69
75
  @report = []
70
76
  end
71
- def get_keys(items, key='GTIN')
72
- items.collect{|item| item[key].first.to_i }
77
+
78
+ def get_keys(items, key = "GTIN")
79
+ items.collect { |item| item[key].first.to_i }
73
80
  end
81
+
74
82
  def get_names(items)
75
- items.collect{|item| item.keys}.flatten.uniq.sort
83
+ items.collect { |item| item.keys }.flatten.uniq.sort
76
84
  end
85
+
77
86
  def compare
78
87
  show_header("Start comparing #{@left.filename} with #{@right.filename}")
79
88
  (@left.components & @right.components).each do |name|
80
- begin
81
- puts "\n#{Time.now.strftime("%H:%M:%S")}: Comparing #{name} in #{@left.basename} with #{@right.basename}"
82
- key = StammXML.get_component_key_name(name)
83
- left_items = @left.get_items(name)
84
- next unless left_items
85
- right_items = @right.get_items(name)
86
- next unless right_items
87
- @diff_stat[name] = {}
88
- @occurrences[name] = {}
89
- @diff_stat[name][NR_COMPARED] = 0
90
- l_names = get_names(left_items)
91
- r_names = get_names(right_items)
92
- compare_names = l_names & r_names
93
- l_keys = get_keys(left_items, key)
94
- r_keys = get_keys(right_items, key)
95
- (l_keys & r_keys).each do |id|
96
- compare_details(name, compare_names, id)
97
- end
98
- key_results_details(name, compare_names, l_keys, r_keys)
99
- rescue => error
100
- puts "Execution failed with #{error}"
89
+ puts "\n#{Time.now.strftime("%H:%M:%S")}: Comparing #{name} in #{@left.basename} with #{@right.basename}"
90
+ key = StammXML.get_component_key_name(name)
91
+ left_items = @left.get_items(name)
92
+ next unless left_items
93
+ right_items = @right.get_items(name)
94
+ next unless right_items
95
+ @diff_stat[name] = {}
96
+ @occurrences[name] = {}
97
+ @diff_stat[name][NR_COMPARED] = 0
98
+ l_names = get_names(left_items)
99
+ r_names = get_names(right_items)
100
+ compare_names = l_names & r_names
101
+ l_keys = get_keys(left_items, key)
102
+ r_keys = get_keys(right_items, key)
103
+ (l_keys & r_keys).each do |id|
104
+ compare_details(name, compare_names, id)
101
105
  end
106
+ key_results_details(name, compare_names, l_keys, r_keys)
107
+ rescue => error
108
+ puts "Execution failed with #{error}"
102
109
  end
103
110
  show_header("Summary comparing #{@left.filename} with #{@right.filename}")
104
111
  puts "Ignored differences in #{@options[:fields_to_ignore]}. Signaled when differences in #{@options[:fields_as_floats]} were bigger than #{@options[:min_diff_for_floats]}"
@@ -116,28 +123,31 @@ module Oddb2xml
116
123
  puts "Execution failed with #{error}"
117
124
  raise error
118
125
  end
126
+
119
127
  private
120
- NR_COMPARED = 'NR_COMPARED'
121
- COUNT = '_count'
128
+
129
+ NR_COMPARED = "NR_COMPARED"
130
+ COUNT = "_count"
122
131
  def show_header(header)
123
132
  text = Oddb2xml.log_timestamp(header)
124
133
  pad = 5
125
134
  puts
126
- puts '-'*(text.length+2*pad)
127
- puts ''.ljust(pad) + text
128
- puts '-'*(text.length+2*pad)
135
+ puts "-" * (text.length + 2 * pad)
136
+ puts "".ljust(pad) + text
137
+ puts "-" * (text.length + 2 * pad)
129
138
  puts
130
139
  end
140
+
131
141
  def compare_details(component_name, compare_names, id)
132
142
  l_item = @left.get_item(component_name, id)
133
143
  r_item = @right.get_item(component_name, id)
134
144
  found_one = false
135
145
  length = 32
136
146
  found = false
137
- detail_name = l_item['DSCR'] ? l_item['DSCR'].first[0..length-1].rjust(length) : ''.rjust(length)
147
+ detail_name = l_item["DSCR"] ? l_item["DSCR"].first[0..length - 1].rjust(length) : "".rjust(length)
138
148
  details = "Diff in #{id.to_s.ljust(15)} #{detail_name}"
139
149
  diff_name = component_name
140
- diff_name += 'S' unless /S$/.match(diff_name)
150
+ diff_name += "S" unless /S$/.match?(diff_name)
141
151
  @diff_stat[diff_name] ||= {}
142
152
  @occurrences[diff_name] ||= {}
143
153
  @diff_stat[diff_name][NR_COMPARED] ||= 0
@@ -154,33 +164,34 @@ module Oddb2xml
154
164
  r_float = r_value ? r_value.first.to_f : 0.0
155
165
  next if (l_float - r_float).abs < @options[:min_diff_for_floats]
156
166
  end
157
- next if (r_value.is_a?(Array) && '--missing--'.eql?(r_value.first)) || (l_value.is_a?(Array) && '--missing--'.eql?(l_value.first))
158
- # TODO: get_field_from_v5_product
167
+ next if (r_value.is_a?(Array) && "--missing--".eql?(r_value.first)) || (l_value.is_a?(Array) && "--missing--".eql?(l_value.first))
168
+ # TODO: get_field_from_v5_product
159
169
  next if r_value.to_s.eql?(l_value.to_s)
160
170
  next if r_value.to_s.upcase.eql?(l_value.to_s.upcase) && @options[:case_insensitive]
161
171
  details += " #{sub_key}: '#{l_value}' != '#{r_value}'"
162
172
  found = found_one = true
163
173
  @diff_stat[diff_name][sub_key] += 1
164
174
  end
165
- puts details.gsub(/[\[\]]/,'') if found
175
+ puts details.gsub(/[\[\]]/, "") if found
166
176
  end
167
177
 
168
178
  def show_keys(keys, batch_size = 20)
169
179
  0.upto(keys.size) do |idx|
170
180
  next unless idx % batch_size == 0
171
- puts ' ' + keys[idx..(idx + batch_size-1)].join(' ')
181
+ puts " " + keys[idx..(idx + batch_size - 1)].join(" ")
172
182
  end
173
183
  end
184
+
174
185
  def key_results_details(component_name, compare_names, l_keys, r_keys)
175
- component_name += 'S' unless /S$/.match(component_name)
176
- @report << "#{component_name}: Found #{l_keys.size} items only in #{@left.basename} #{r_keys.size} items only in #{@right.basename}, compared #{@diff_stat[component_name][NR_COMPARED]} items"
186
+ component_name += "S" unless /S$/.match?(component_name)
187
+ @report << "#{component_name}: Found #{l_keys.size} items only in #{@left.basename} #{r_keys.size} items only in #{@right.basename}, compared #{@diff_stat[component_name][NR_COMPARED]} items"
177
188
  keys = r_keys - l_keys
178
- head = "#{component_name}: #{(keys).size} keys only in #{@right.basename}"
189
+ head = "#{component_name}: #{keys.size} keys only in #{@right.basename}"
179
190
  puts "#{head}: Keys were #{keys.size}"
180
191
  show_keys(keys)
181
192
  @report << head
182
193
  keys = l_keys - r_keys
183
- head = "#{component_name}: #{(keys).size} keys only in #{@left.basename}"
194
+ head = "#{component_name}: #{keys.size} keys only in #{@left.basename}"
184
195
  puts "#{head}: Keys were #{keys.size}"
185
196
  show_keys(keys)
186
197
  @report << head
@@ -1,554 +1,572 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is shared since oddb2xml 2.0.0 (lib/oddb2xml/parse_compositions.rb)
4
2
  # with oddb.org src/plugin/parse_compositions.rb
5
3
  #
6
4
  # It allows an easy parsing of the column P Zusammensetzung of the swissmedic packages.xlsx file
7
5
  #
8
6
 
9
- require 'parslet'
10
- require 'parslet/convenience'
11
- include Parslet
7
+ require "parslet"
8
+ require "parslet/convenience"
12
9
 
13
10
  class CompositionParser < Parslet::Parser
14
-
11
+ include Parslet
15
12
  # Single character rules
16
- rule(:lparen) { str('(') }
17
- rule(:rparen) { str(')') }
18
- rule(:comma) { str(',') }
13
+ rule(:lparen) { str("(") }
14
+ rule(:rparen) { str(")") }
15
+ rule(:comma) { str(",") }
19
16
 
20
- rule(:space) { match('\s').repeat(1) }
21
- rule(:space?) { space.maybe }
17
+ rule(:space) { match('\s').repeat(1) }
18
+ rule(:space?) { space.maybe }
22
19
 
23
20
  # Things
24
- rule(:digit) { match('[0-9]') }
21
+ rule(:digit) { match("[0-9]") }
25
22
  rule(:digits) { digit.repeat(1) }
26
23
  rule(:number) {
27
24
  (
28
- str('-').maybe >> (
29
- str('0') | (match('[1-9]') >> match('[0-9\']').repeat)
25
+ str("-").maybe >> (
26
+ str("0") | (match("[1-9]") >> match("[0-9']").repeat)
30
27
  ) >> (
31
- (str('*') >> digit.repeat(1)).maybe >>
32
- (match(['.,^']) >> digit.repeat(1)).repeat(1)
33
- ).maybe >> (
34
- match('[eE]') >> (str('+') | str('-')).maybe >> digit.repeat(1)
28
+ (str("*") >> digit.repeat(1)).maybe >>
29
+ (match([".,^"]) >> digit.repeat(1)).repeat(1)
30
+ ).maybe >> (
31
+ match("[eE]") >> (str("+") | str("-")).maybe >> digit.repeat(1)
35
32
  ).maybe
36
33
  )
37
34
  }
38
- rule(:radio_isotop) { match['a-zA-Z'].repeat(1) >> lparen >> digits >> str('-') >> match['a-zA-Z'].repeat(1-3) >> rparen >>
39
- ((space? >> match['a-zA-Z']).repeat(1)).repeat(0)
40
- } # e.g. Xenonum (133-Xe) or yttrii(90-Y) chloridum zum Kalibrierungszeitpunkt
41
- rule(:ratio_value) { match['0-9:\-\.,'].repeat(1) >> space?} # eg. ratio: 1:1, ratio: 1:1.5-2.4., ratio: 1:0.68-0.95, 1:4,1
35
+ rule(:radio_isotop) {
36
+ match["a-zA-Z"].repeat(1) >> lparen >> digits >> str("-") >> match["a-zA-Z"].repeat(1 - 3) >> rparen >>
37
+ ((space? >> match["a-zA-Z"]).repeat(1)).repeat(0)
38
+ } # e.g. Xenonum (133-Xe) or yttrii(90-Y) chloridum zum Kalibrierungszeitpunkt
39
+ rule(:ratio_value) { match['0-9:\-\.,'].repeat(1) >> space? } # eg. ratio: 1:1, ratio: 1:1.5-2.4., ratio: 1:0.68-0.95, 1:4,1
42
40
 
43
41
  # handle stuff like acidum 9,11-linolicum or 2,2'-methylen-bis(6-tert.-butyl-4-methyl-phenolum) specially. it must contain at least one a-z
44
- rule(:umlaut) { match(['éàèèçïöäüâ']) }
45
- rule(:identifier_D12) { match['a-zA-Z'] >> match['0-9'].repeat(1) }
42
+ rule(:umlaut) { match(["éàèèçïöäüâ"]) }
43
+ rule(:identifier_D12) { match["a-zA-Z"] >> match["0-9"].repeat(1) }
46
44
 
47
45
  # TODO: why do we have to hard code these identifiers?
48
46
  rule(:fix_coded_identifiers) {
49
47
  str("2,2'-methylen-bis(6-tert.-butyl-4-methyl-phenolum)") |
50
- str('A + B') |
51
- str('CRM 197') |
52
- str('F.E.I.B.A.') |
53
- str('LA ') >> digit.repeat(1,2) >> str('% TM') |
54
- str('TM:') | str('&') |
55
- str('ethanol.') |
56
- str('poloxamerum 238') |
57
- str('polysorbatum ') >> digit >> digit
48
+ str("A + B") |
49
+ str("CRM 197") |
50
+ str("F.E.I.B.A.") |
51
+ str("LA ") >> digit.repeat(1, 2) >> str("% TM") |
52
+ str("TM:") | str("&") |
53
+ str("ethanol.") |
54
+ str("poloxamerum 238") |
55
+ str("polysorbatum ") >> digit >> digit
58
56
  }
59
57
 
60
58
  # TODO: Sind diese Abkürzung wirklich Teil eines Substanznamens?
61
- rule(:identifier_abbrev_with_comma) {
62
- str('aquos') |
63
- str('ca.') |
64
- str('deklar.') |
65
- str('spag.') |
66
- str('spec.') |
67
- str('spp.') |
68
- str('ssp.') |
69
- str('var.')
59
+ rule(:identifier_abbrev_with_comma) {
60
+ str("aquos") |
61
+ str("ca.") |
62
+ str("deklar.") |
63
+ str("spag.") |
64
+ str("spec.") |
65
+ str("spp.") |
66
+ str("ssp.") |
67
+ str("var.")
70
68
  }
71
69
  rule(:fix_coded_doses) {
72
- digit >> digit.maybe >> space >> str('per centum ') >> str('q.s.').maybe |
73
- str('50/50') |
74
- str('1g/9.6 cm²') |
75
- str('9 g/L 5.4 ml')
76
- }
77
- rule(:identifier) { fix_coded_identifiers |
78
- identifier_abbrev_with_comma |
79
- fix_coded_doses |
80
- str('q.s.') |
81
- identifier_D12 |
82
- identifier_without_comma |
83
- identifier_with_comma
84
- }
70
+ digit >> digit.maybe >> space >> str("per centum ") >> str("q.s.").maybe |
71
+ str("50/50") |
72
+ str("1g/9.6 cm²") |
73
+ str("9 g/L 5.4 ml")
74
+ }
75
+ rule(:identifier) {
76
+ fix_coded_identifiers |
77
+ identifier_abbrev_with_comma |
78
+ fix_coded_doses |
79
+ str("q.s.") |
80
+ identifier_D12 |
81
+ identifier_without_comma |
82
+ identifier_with_comma
83
+ }
85
84
 
86
85
  rule(:identifier_with_comma) {
87
- match['0-9,\-'].repeat(0) >> (match['a-zA-Z']|umlaut) >> (match(['_,']).maybe >> (match['0-9a-zA-Z\-\'\/'] | umlaut)).repeat(0)
86
+ match['0-9,\-'].repeat(0) >> (match["a-zA-Z"] | umlaut) >> (match(["_,"]).maybe >> (match['0-9a-zA-Z\-\'\/'] | umlaut)).repeat(0)
88
87
  }
89
88
 
90
89
  rule(:identifier_without_comma) {
91
- match['0-9\',\-'].repeat(0) >> (match['a-zA-Z']|umlaut) >> (match(['_']).maybe >> (match['0-9a-zA-Z\-\'\/'] | umlaut)).repeat(0) >>
92
- lparen >> (rparen.absent? >> any).repeat(1) >> rparen
90
+ match['0-9\',\-'].repeat(0) >> (match["a-zA-Z"] | umlaut) >> (match(["_"]).maybe >> (match['0-9a-zA-Z\-\'\/'] | umlaut)).repeat(0) >>
91
+ lparen >> (rparen.absent? >> any).repeat(1) >> rparen
93
92
  }
94
- rule(:one_word) { match['a-zA-Z'] >> match['0-9'].repeat(1) | match['a-zA-Z'].repeat(1) }
93
+ rule(:one_word) { match["a-zA-Z"] >> match["0-9"].repeat(1) | match["a-zA-Z"].repeat(1) }
95
94
  rule(:in_parent) { lparen >> one_word.repeat(1) >> rparen }
96
95
  rule(:words_nested) { one_word.repeat(1) >> in_parent.maybe >> space? >> one_word.repeat(0) }
97
96
  # dose
98
97
  # 150 U.I. hFSH et 150 U.I. hLH
99
98
  rule(:units) {
100
- str('cm²') |
101
- str('g/dm²') |
102
- str('g/l') |
103
- str('g/L') |
104
- str('% V/V') |
105
- str('µg/24 h') |
106
- str('µg/g') |
107
- str('µg') |
108
- str('ng') |
109
- str('guttae') |
110
- str('mg/g') |
111
- str('mg/ml') |
112
- str('MBq/ml') |
113
- str('MBq') |
114
- str('CFU') |
115
- str('mg') |
116
- str('Mg') |
117
- str('kJ') |
118
- str('G') |
119
- str('g') |
120
- str('I.E.') |
121
- str('l') |
122
- str('µl') |
123
- str('U. Ph. Eur.') |
124
- str('ml') |
125
- str('µmol') |
126
- str('mmol/l') |
127
- str('mmol') |
128
- str('Mio CFU') |
129
- str('Mio U.I.') |
130
- str('Mio U.') |
131
- str('Mio. U.I.') |
132
- str('Mio. U.') |
133
- str('Mia. U.I.') |
134
- str('Mia. U.') |
135
- str('S.U.') |
136
- str('U. Botox') |
137
- str('U.I. hFSH') |
138
- str('U.I. hCG') |
139
- str('U.I. hLH') |
140
- str('U.I.') |
141
- str('U./ml') |
142
- str('U.K.I.') |
143
- str('U.') |
144
- str('Mia.') |
145
- str('Mrd.') |
146
- str('% m/m') |
147
- str('% m/m') |
148
- str('%')
99
+ str("cm²") |
100
+ str("g/dm²") |
101
+ str("g/l") |
102
+ str("g/L") |
103
+ str("% V/V") |
104
+ str("µg/24 h") |
105
+ str("µg/g") |
106
+ str("µg") |
107
+ str("ng") |
108
+ str("guttae") |
109
+ str("mg/g") |
110
+ str("mg/ml") |
111
+ str("MBq/ml") |
112
+ str("MBq") |
113
+ str("CFU") |
114
+ str("mg") |
115
+ str("Mg") |
116
+ str("kJ") |
117
+ str("G") |
118
+ str("g") |
119
+ str("I.E.") |
120
+ str("l") |
121
+ str("µl") |
122
+ str("U. Ph. Eur.") |
123
+ str("ml") |
124
+ str("µmol") |
125
+ str("mmol/l") |
126
+ str("mmol") |
127
+ str("Mio CFU") |
128
+ str("Mio U.I.") |
129
+ str("Mio U.") |
130
+ str("Mio. U.I.") |
131
+ str("Mio. U.") |
132
+ str("Mia. U.I.") |
133
+ str("Mia. U.") |
134
+ str("S.U.") |
135
+ str("U. Botox") |
136
+ str("U.I. hFSH") |
137
+ str("U.I. hCG") |
138
+ str("U.I. hLH") |
139
+ str("U.I.") |
140
+ str("U./ml") |
141
+ str("U.K.I.") |
142
+ str("U.") |
143
+ str("Mia.") |
144
+ str("Mrd.") |
145
+ str("% m/m") |
146
+ str("% m/m") |
147
+ str("%")
149
148
  }
150
149
  rule(:dose_unit) { units.as(:unit) }
151
- rule(:qty_range) { (number >> space? >> (str('+/-') | str(' - ') | str(' -') | str('-') | str('±') ) >> space? >> number).as(:qty_range) }
152
- rule(:qty_unit) { dose_qty >> (space >> dose_unit).maybe }
153
- rule(:dose_qty) { number.as(:qty) }
154
- rule(:min_max) { (str('min.') | str('max.') | str('ca.') | str('<') ) >> space? }
150
+ rule(:qty_range) { (number >> space? >> (str("+/-") | str(" - ") | str(" -") | str("-") | str("±")) >> space? >> number).as(:qty_range) }
151
+ rule(:qty_unit) { dose_qty >> (space >> dose_unit).maybe }
152
+ rule(:dose_qty) { number.as(:qty) }
153
+ rule(:min_max) { (str("min.") | str("max.") | str("ca.") | str("<")) >> space? }
155
154
  # 75 U.I. hFSH et 75 U.I. hLH
156
- rule(:dose_fsh) { qty_unit >> space >> str('et') >> space >> qty_unit.as(:dose_right) }
157
- rule(:dose_per) { (digits >> str('/') >> digits).as(:qty)}
158
- rule(:dose) { dose_fsh |
159
- dose_per |
160
- ( min_max.maybe >>
161
- ( (qty_range >> (space >> dose_unit).maybe) | (qty_unit | dose_qty |dose_unit)) >> space? ) >>
162
- str('pro dosi').maybe >> space?
163
- }
164
- rule(:dose_with_unit) { min_max.maybe >>
165
- dose_fsh |
166
- ( qty_range >> space >> dose_unit |
167
- dose_qty >> space >> dose_unit
168
- ) >>
169
- space?
170
- }
171
- rule(:operator) { match('[+]') >> space? }
155
+ rule(:dose_fsh) { qty_unit >> space >> str("et") >> space >> qty_unit.as(:dose_right) }
156
+ rule(:dose_per) { (digits >> str("/") >> digits).as(:qty) }
157
+ rule(:dose) {
158
+ dose_fsh |
159
+ dose_per |
160
+ (min_max.maybe >>
161
+ ((qty_range >> (space >> dose_unit).maybe) | (qty_unit | dose_qty | dose_unit)) >> space?) >>
162
+ str("pro dosi").maybe >> space?
163
+ }
164
+ rule(:dose_with_unit) {
165
+ min_max.maybe >>
166
+ dose_fsh |
167
+ (qty_range >> space >> dose_unit |
168
+ dose_qty >> space >> dose_unit
169
+ ) >>
170
+ space?
171
+ }
172
+ rule(:operator) { match("[+]") >> space? }
172
173
 
173
174
  # Grammar parts
174
- rule(:useage) { (any >> str('berzug:')) | # match Überzug
175
- str('antiox.:') |
176
- str('arom.:') |
177
- str('conserv.:') |
178
- str('color.:')
179
- }
175
+ rule(:useage) {
176
+ (any >> str("berzug:")) | # match Überzug
177
+ str("antiox.:") |
178
+ str("arom.:") |
179
+ str("conserv.:") |
180
+ str("color.:")
181
+ }
180
182
 
181
183
  # Match Wirkstoffe like E 270
182
- rule(:lebensmittel_zusatz) { str('E').as(:lebensmittel_zusatz) >> space >>
183
- (digits >> match['(a-z)'].repeat(0,3)).as(:digits) >>
184
- (space >> dose.as(:dose_lebensmittel_zusatz)).maybe >> space?
185
-
186
- }
187
- # DER: 1:4 or DER: 3.5:1 or DER: 6-8:1 or DER: 4.0-9.0:1'
188
- rule(:der_identifier) { str('DER:') >> space >> digit >> match['0-9\.\-:'].repeat }
184
+ rule(:lebensmittel_zusatz) {
185
+ str("E").as(:lebensmittel_zusatz) >> space >>
186
+ (digits >> match["(a-z)"].repeat(0, 3)).as(:digits) >>
187
+ (space >> dose.as(:dose_lebensmittel_zusatz)).maybe >> space?
188
+ }
189
+ # DER: 1:4 or DER: 3.5:1 or DER: 6-8:1 or DER: 4.0-9.0:1'
190
+ rule(:der_identifier) { str("DER:") >> space >> digit >> match['0-9\.\-:'].repeat }
189
191
  rule(:der) { (der_identifier).as(:substance_name) >> space? >> dose.maybe.as(:dose) }
190
192
  rule(:forbidden_in_substance_name) {
191
- min_max |
192
- useage |
193
- excipiens_identifiers |
194
- pro_identifiers |
195
- corresp_substance_label |
196
- (digits.repeat(1) >> space >> str(':')) | # match 50 %
197
- str(', corresp.') |
198
- str('Beutel: ') |
199
- str('Mio ') |
200
- str('ad emulsionem') |
201
- str('ad globulos') |
202
- str('ad pulverem') |
203
- str('ad q.s. ') |
204
- str('ad solutionem') |
205
- str('ad suspensionem') |
206
- str('ana partes') |
207
- str('ana ') |
208
- str('aqua ad ') |
209
- str('aqua q.s. ') |
210
- str('corresp. ca.,') |
211
- str('et ') |
212
- str('excipiens') |
213
- str('partes') |
214
- str('pro capsula') |
215
- str('pro dosi') |
216
- str('pro vitroe') |
217
- str('q.s. ad ') |
218
- str('q.s. pro ') |
219
- str('ratio:') |
220
- str('ut alia: ') |
221
- str('ut ')
222
- }
193
+ min_max |
194
+ useage |
195
+ excipiens_identifiers |
196
+ pro_identifiers |
197
+ corresp_substance_label |
198
+ (digits.repeat(1) >> space >> str(":")) | # match 50 %
199
+ str(", corresp.") |
200
+ str("Beutel: ") |
201
+ str("Mio ") |
202
+ str("ad emulsionem") |
203
+ str("ad globulos") |
204
+ str("ad pulverem") |
205
+ str("ad q.s. ") |
206
+ str("ad solutionem") |
207
+ str("ad suspensionem") |
208
+ str("ana partes") |
209
+ str("ana ") |
210
+ str("aqua ad ") |
211
+ str("aqua q.s. ") |
212
+ str("corresp. ca.,") |
213
+ str("et ") |
214
+ str("excipiens") |
215
+ str("partes") |
216
+ str("pro capsula") |
217
+ str("pro dosi") |
218
+ str("pro vitroe") |
219
+ str("q.s. ad ") |
220
+ str("q.s. pro ") |
221
+ str("ratio:") |
222
+ str("ut alia: ") |
223
+ str("ut ")
224
+ }
223
225
  rule(:name_without_parenthesis) {
224
226
  (
225
- (str('(') | forbidden_in_substance_name).absent? >>
226
- (radio_isotop | str('> 1000') | str('> 500') | identifier.repeat(1) >> str('.').maybe) >>
227
+ (str("(") | forbidden_in_substance_name).absent? >>
228
+ (radio_isotop | str("> 1000") | str("> 500") | identifier.repeat(1) >> str(".").maybe) >>
227
229
  space?
228
230
  ).repeat(1)
229
231
  }
230
232
 
231
- rule(:part_with_parenthesis) { lparen >> ( (lparen | rparen).absent? >> any).repeat(1) >>
232
- (part_with_parenthesis | rparen >> str('-like:') | rparen ) >> space?
233
- }
233
+ rule(:part_with_parenthesis) {
234
+ lparen >> ((lparen | rparen).absent? >> any).repeat(1) >>
235
+ (part_with_parenthesis | rparen >> str("-like:") | rparen) >> space?
236
+ }
234
237
  rule(:name_with_parenthesis) {
235
238
  forbidden_in_substance_name.absent? >>
236
- ((comma | lparen).absent? >> any).repeat(0) >> part_with_parenthesis >>
237
- (forbidden_in_substance_name.absent? >> (identifier.repeat(1) | part_with_parenthesis | rparen) >> space?).repeat(0)
239
+ ((comma | lparen).absent? >> any).repeat(0) >> part_with_parenthesis >>
240
+ (forbidden_in_substance_name.absent? >> (identifier.repeat(1) | part_with_parenthesis | rparen) >> space?).repeat(0)
238
241
  }
239
- rule(:substance_name) { (
242
+ rule(:substance_name) {
243
+ (
240
244
  name_with_parenthesis |
241
245
  name_without_parenthesis
242
246
  ) >>
243
- str('pro dosi').maybe >> space?
244
- }
245
- rule(:simple_substance) { substance_name.as(:substance_name) >> space? >> dose.maybe.as(:dose)}
246
- rule(:simple_subtance_with_digits_in_name_and_dose) {
247
+ str("pro dosi").maybe >> space?
248
+ }
249
+ rule(:simple_substance) { substance_name.as(:substance_name) >> space? >> dose.maybe.as(:dose) }
250
+ rule(:simple_subtance_with_digits_in_name_and_dose) {
247
251
  substance_lead.maybe.as(:more_info) >> space? >>
248
- (name_without_parenthesis >> space? >> ((digits.repeat(1) >> (str(' %') | str('%')) | digits.repeat(1)))).as(:substance_name) >>
249
- space >> dose_with_unit.as(:dose)
252
+ (name_without_parenthesis >> space? >> ((digits.repeat(1) >> (str(" %") | str("%")) | digits.repeat(1)))).as(:substance_name) >>
253
+ space >> dose_with_unit.as(:dose)
250
254
  }
251
255
 
252
-
253
256
  rule(:substance_more_info) { # e.g. "acari allergeni extractum 5000 U.:
254
- (str('ratio:').absent? >> (identifier|digits) >> space?).repeat(1) >> space? >> (str('U.:') | str(':')| str('.:')) >> space?
255
- }
257
+ (str("ratio:").absent? >> (identifier | digits) >> space?).repeat(1) >> space? >> (str("U.:") | str(":") | str(".:")) >> space?
258
+ }
256
259
 
257
260
  rule(:pro_identifiers) {
258
- str('ut aqua ad iniectabilia q.s. ad emulsionem pro ') |
259
- str('aqua ').maybe >> str('ad iniectabilia q.s. ad solutionem pro ') |
260
- str('aqua ').maybe >> str('ad solutionem pro ') |
261
- str('aqua ').maybe >> str('q.s. ad emulsionem pro ') |
262
- str('aqua ').maybe >> str('q.s. ad gelatume pro ') |
263
- str('aqua ').maybe >> str('q.s. ad solutionem pro ') |
264
- str('aqua ').maybe >> str('q.s. ad suspensionem pro ') |
265
- str('doses pro vase ') |
266
- str('excipiens ad emulsionem pro ') |
267
- str('excipiens ad pulverem pro ') |
268
- str('excipiens ad solutionem pro ') |
269
- str('pro vase ') |
270
- str('q.s. ad pulverem pro ')
271
- }
272
- rule(:excipiens_dose) { pro_identifiers.as(:excipiens_description) >> space? >> dose.as(:dose) >> space? >> ratio.maybe.as(:ratio) >>
273
- space? >> str('corresp.').maybe >> space? >> dose.maybe.as(:dose_corresp)
274
- }
275
-
276
- rule(:excipiens_identifiers) {
277
- str('ad globulos') |
278
- str('ad pulverem') |
279
- str('ad solutionem') |
280
- str('aether q.s.') |
281
- str('ana partes') |
282
- str('aqua ad iniectabilia q.s. ad solutionem') |
283
- str('aqua ad iniectabilia') |
284
- str('aqua q.s. ad') |
285
- str('excipiens pro compresso obducto') |
286
- str('excipiens pro compresso') |
287
- str('excipiens pro praeparatione') |
288
- str('excipiens') |
289
- str('pro charta') |
290
- str('pro praeparatione') |
291
- str('pro vitro') |
292
- str('q.s. ad') |
293
- str('q.s. pro praeparatione') |
294
- str('saccharum ad') |
295
- str('solvens (i.v.): aqua ad iniectabilia')
296
- }
297
-
298
- rule(:excipiens) { substance_lead.maybe.as(:more_info) >> space? >>
299
- ( excipiens_dose | (excipiens_identifiers >> any.repeat(0)).as(:excipiens_description)) >>
300
- any.repeat(0)
301
- }
302
-
303
- rule(:substance_lead) { useage >> space? |
304
- str('Beutel:') >> space? |
305
- str('residui:') >> space? |
306
- str('mineralia:') >> str(':') >> space? |
307
- str('Solvens:') >> space? |
308
- substance_more_info
309
- }
261
+ str("ut aqua ad iniectabilia q.s. ad emulsionem pro ") |
262
+ str("aqua ").maybe >> str("ad iniectabilia q.s. ad solutionem pro ") |
263
+ str("aqua ").maybe >> str("ad solutionem pro ") |
264
+ str("aqua ").maybe >> str("q.s. ad emulsionem pro ") |
265
+ str("aqua ").maybe >> str("q.s. ad gelatume pro ") |
266
+ str("aqua ").maybe >> str("q.s. ad solutionem pro ") |
267
+ str("aqua ").maybe >> str("q.s. ad suspensionem pro ") |
268
+ str("doses pro vase ") |
269
+ str("excipiens ad emulsionem pro ") |
270
+ str("excipiens ad pulverem pro ") |
271
+ str("excipiens ad solutionem pro ") |
272
+ str("pro vase ") |
273
+ str("q.s. ad pulverem pro ")
274
+ }
275
+ rule(:excipiens_dose) {
276
+ pro_identifiers.as(:excipiens_description) >> space? >> dose.as(:dose) >> space? >> ratio.maybe.as(:ratio) >>
277
+ space? >> str("corresp.").maybe >> space? >> dose.maybe.as(:dose_corresp)
278
+ }
279
+
280
+ rule(:excipiens_identifiers) {
281
+ str("ad globulos") |
282
+ str("ad pulverem") |
283
+ str("ad solutionem") |
284
+ str("aether q.s.") |
285
+ str("ana partes") |
286
+ str("aqua ad iniectabilia q.s. ad solutionem") |
287
+ str("aqua ad iniectabilia") |
288
+ str("aqua q.s. ad") |
289
+ str("excipiens pro compresso obducto") |
290
+ str("excipiens pro compresso") |
291
+ str("excipiens pro praeparatione") |
292
+ str("excipiens") |
293
+ str("pro charta") |
294
+ str("pro praeparatione") |
295
+ str("pro vitro") |
296
+ str("q.s. ad") |
297
+ str("q.s. pro praeparatione") |
298
+ str("saccharum ad") |
299
+ str("solvens (i.v.): aqua ad iniectabilia")
300
+ }
301
+
302
+ rule(:excipiens) {
303
+ substance_lead.maybe.as(:more_info) >> space? >>
304
+ (excipiens_dose | (excipiens_identifiers >> any.repeat(0)).as(:excipiens_description)) >>
305
+ any.repeat(0)
306
+ }
307
+
308
+ rule(:substance_lead) {
309
+ useage >> space? |
310
+ str("Beutel:") >> space? |
311
+ str("residui:") >> space? |
312
+ str("mineralia:") >> str(":") >> space? |
313
+ str("Solvens:") >> space? |
314
+ substance_more_info
315
+ }
310
316
  rule(:corresp_substance_label) {
311
- str(', corresp. ca.,') |
312
- str('corresp. ca.,') |
313
- str('corresp.,') |
314
- str('corresp.') |
315
- str(', corresp.')
316
- }
317
- rule(:ratio) { str('ratio:') >> space >> ratio_value }
318
-
319
- rule(:solvens) { (str('Solvens:') | str('Solvens (i.m.):'))>> space >> (any.repeat).as(:more_info) >> space? >>
320
- (substance.as(:substance) >> str('/L').maybe).maybe >>
321
- any.maybe
322
- }
323
- # Perhaps we could have some syntax sugar to make this more easy?
324
- #
325
- def tag(opts={})
326
- close = opts[:close] || false
327
- end
328
-
329
- # TODO: what does ut alia: impl?
317
+ str(", corresp. ca.,") |
318
+ str("corresp. ca.,") |
319
+ str("corresp.,") |
320
+ str("corresp.") |
321
+ str(", corresp.")
322
+ }
323
+ rule(:ratio) { str("ratio:") >> space >> ratio_value }
324
+
325
+ rule(:solvens) {
326
+ (str("Solvens:") | str("Solvens (i.m.):")) >> space >> (any.repeat).as(:more_info) >> space? >>
327
+ (substance.as(:substance) >> str("/L").maybe).maybe >>
328
+ any.maybe
329
+ }
330
+ # Perhaps we could have some syntax sugar to make this more easy?
331
+ #
332
+ def tag(opts = {})
333
+ opts[:close] || false
334
+ end
335
+
336
+ # TODO: what does ut alia: impl?
330
337
  rule(:substance_ut) {
331
- (space? >> (str('pro dosi ut ') | str('ut ') ) >>
332
- space? >> str('alia:').absent? >>substance
333
- ) >>
334
- space?
335
- }
338
+ (space? >> (str("pro dosi ut ") | str("ut ")) >>
339
+ space? >> str("alia:").absent? >> substance
340
+ ) >>
341
+ space?
342
+ }
336
343
 
337
344
  rule(:corresp_substance) {
338
- (corresp_substance_label) >> space? >>
339
- (
340
- substance |
341
- dose.as(:dose_corresp_2) |
342
- excipiens.as(:excipiens)
343
- )
345
+ (corresp_substance_label) >> space? >>
346
+ (
347
+ substance |
348
+ dose.as(:dose_corresp_2) |
349
+ excipiens.as(:excipiens)
350
+ )
344
351
  }
345
352
 
346
353
  rule(:substance) {
347
- (
348
- simple_subtance_with_digits_in_name_and_dose |
349
- der |
350
- substance_lead.maybe.as(:more_info) >> space? >> lebensmittel_zusatz |
351
- substance_lead.maybe.as(:more_info) >> space? >> simple_substance >> str('pro dosi').maybe
352
- ).as(:substance) >>
353
- (space? >> str(', ').maybe >> ratio.maybe).as(:ratio) >>
354
+ (
355
+ simple_subtance_with_digits_in_name_and_dose |
356
+ der |
357
+ substance_lead.maybe.as(:more_info) >> space? >> lebensmittel_zusatz |
358
+ substance_lead.maybe.as(:more_info) >> space? >> simple_substance >> str("pro dosi").maybe
359
+ ).as(:substance) >>
360
+ (space? >> str(", ").maybe >> ratio.maybe).as(:ratio) >>
354
361
  space? >> corresp_substance.maybe.as(:chemical_substance) >>
355
362
  space? >> substance_ut.repeat(0).as(:substance_ut)
356
363
  }
357
- rule(:histamin) { str('U = Histamin Equivalent Prick').as(:histamin) }
358
- rule(:praeparatio){ ((one_word >> space?).repeat(1).as(:description) >> str(':') >> space?).maybe >>
359
- (name_with_parenthesis | name_without_parenthesis).repeat(1).as(:substance_name) >>
360
- number.as(:qty) >> space >> str('U.:') >> space? >>
361
- ((identifier >> space?).repeat(1).as(:more_info) >> space?).maybe
362
- }
363
- rule(:substance_separator) { (str(', et ') | comma | str('et ') | str('ut alia: ')) >> space? }
364
- rule(:one_substance) { (praeparatio | histamin | substance) >> space? >> ratio.as(:ratio).maybe >> space? }
365
- rule(:all_substances) { (one_substance >> substance_separator.maybe).repeat(1) >> space? >> excipiens.as(:excipiens).maybe}
366
- rule(:composition) { all_substances }
364
+ rule(:histamin) { str("U = Histamin Equivalent Prick").as(:histamin) }
365
+ rule(:praeparatio) {
366
+ ((one_word >> space?).repeat(1).as(:description) >> str(":") >> space?).maybe >>
367
+ (name_with_parenthesis | name_without_parenthesis).repeat(1).as(:substance_name) >>
368
+ number.as(:qty) >> space >> str("U.:") >> space? >>
369
+ ((identifier >> space?).repeat(1).as(:more_info) >> space?).maybe
370
+ }
371
+ rule(:substance_separator) { (str(", et ") | comma | str("et ") | str("ut alia: ")) >> space? }
372
+ rule(:one_substance) { (praeparatio | histamin | substance) >> space? >> ratio.as(:ratio).maybe >> space? }
373
+ rule(:all_substances) { (one_substance >> substance_separator.maybe).repeat(1) >> space? >> excipiens.as(:excipiens).maybe }
374
+ rule(:composition) { all_substances }
367
375
  rule(:long_labels) {
368
- str('Praeparatio sicca cum solvens: praeparatio sicca:') |
369
- str('Praeparatio cryodesiccata') >> (str(':').absent? >> any).repeat(0) >> str(':') |
370
- str('Tela cum praeparatione (Panel ') >> digit >> str('):')
371
- }
376
+ str("Praeparatio sicca cum solvens: praeparatio sicca:") |
377
+ str("Praeparatio cryodesiccata") >> (str(":").absent? >> any).repeat(0) >> str(":") |
378
+ str("Tela cum praeparatione (Panel ") >> digit >> str("):")
379
+ }
372
380
  rule(:label_id) {
373
- (
374
- str('V') |
375
- str('IV') |
376
- str('III') |
377
- str('II') |
378
- str('I') |
379
- str('A') |
380
- str('B') |
381
- str('C') |
382
- str('D') |
383
- str('E')
381
+ (
382
+ str("V") |
383
+ str("IV") |
384
+ str("III") |
385
+ str("II") |
386
+ str("I") |
387
+ str("A") |
388
+ str("B") |
389
+ str("C") |
390
+ str("D") |
391
+ str("E")
384
392
  )
385
393
  }
386
- rule(:label_separator) { (str('):') | str(')')) }
387
- rule(:label) { label_id.as(:label) >> space? >>
388
- label_separator >> str(',').absent? >>
389
- (space? >> (match(/[^:]/).repeat(0)).as(:label_description) >> str(':') >> space).maybe
394
+ rule(:label_separator) { (str("):") | str(")")) }
395
+ rule(:label) {
396
+ label_id.as(:label) >> space? >>
397
+ label_separator >> str(",").absent? >>
398
+ (space? >> (match(/[^:]/).repeat(0)).as(:label_description) >> str(":") >> space).maybe
399
+ }
400
+ rule(:leading_label) {
401
+ label_id >> label_separator >> (str(" et ") | str(", ") | str(" pro usu: ") | space) >>
402
+ label_id >> label_separator >> any.repeat(1) |
403
+ long_labels.as(:label) |
404
+ label
390
405
  }
391
- rule(:leading_label) { label_id >> label_separator >> (str(' et ') | str(', ') | str(' pro usu: ') | space) >>
392
- label_id >> label_separator >> any.repeat(1) |
393
- long_labels.as(:label) |
394
- label
395
- }
396
406
  rule(:corresp_label) {
397
- str('aqua ') |
398
- str('excipiens ') |
399
- str('doses ') |
400
- str('Pulver: ') |
401
- str('Diluens: ') |
402
- str('Solutio reconstituta:') |
403
- str('Corresp., ') |
404
- str('Corresp. ') |
405
- str('corresp. ')
406
- }
407
- rule(:corresp_line) { corresp_label >> any.repeat(1).as(:corresp) |
408
- ((label_id >> label_separator >> space? >> str('et ').maybe).repeat(1) >> any.repeat(1)).as(:corresp)
409
- }
407
+ str("aqua ") |
408
+ str("excipiens ") |
409
+ str("doses ") |
410
+ str("Pulver: ") |
411
+ str("Diluens: ") |
412
+ str("Solutio reconstituta:") |
413
+ str("Corresp., ") |
414
+ str("Corresp. ") |
415
+ str("corresp. ")
416
+ }
417
+ rule(:corresp_line) {
418
+ corresp_label >> any.repeat(1).as(:corresp) |
419
+ ((label_id >> label_separator >> space? >> str("et ").maybe).repeat(1) >> any.repeat(1)).as(:corresp)
420
+ }
410
421
  rule(:corresp_line_neu) { corresp_label >> any.repeat(1).as(:corresp) }
411
422
 
412
423
  rule(:solvens_label) {
413
- str('Solvens (i.v.)') |
414
- str('Solvens (i.m.)') |
415
- str('Solvens')
424
+ str("Solvens (i.v.)") |
425
+ str("Solvens (i.m.)") |
426
+ str("Solvens")
416
427
  }
417
- rule(:solvens_line) { solvens_label.as(:label) >> (str(': ') >> composition.repeat(1).as(:composition) | any.repeat(1).as(:corresp))}
428
+ rule(:solvens_line) { solvens_label.as(:label) >> (str(": ") >> composition.repeat(1).as(:composition) | any.repeat(1).as(:corresp)) }
418
429
 
419
430
  rule(:multiple_et_line) {
420
- ((label_id >> label_separator >> space? >> (str('pro usu') |str('et '))).repeat(1) >> any.repeat(1)).as(:corresp)
431
+ ((label_id >> label_separator >> space? >> (str("pro usu") | str("et "))).repeat(1) >> any.repeat(1)).as(:corresp)
421
432
  }
422
433
 
423
- rule(:polvac) { label_id.as(:label) >> label_separator >> space? >> composition.as(:composition) >> space? >> str('.').maybe >> space? }
434
+ rule(:polvac) { label_id.as(:label) >> label_separator >> space? >> composition.as(:composition) >> space? >> str(".").maybe >> space? }
424
435
 
425
- rule(:label_comment_excipiens) { label >> space? >> excipiens.as(:excipiens) >> space? >> str('.').maybe >> space? }
436
+ rule(:label_comment_excipiens) { label >> space? >> excipiens.as(:excipiens) >> space? >> str(".").maybe >> space? }
426
437
 
427
- rule(:label_id_composition) { label_id.as(:label) >> label_separator >>
428
- ((space >> identifier).repeat(1) >> str(':')).maybe.as(:label_description) >>
429
- composition.as(:composition) }
438
+ rule(:label_id_composition) {
439
+ label_id.as(:label) >> label_separator >>
440
+ ((space >> identifier).repeat(1) >> str(":")).maybe.as(:label_description) >>
441
+ composition.as(:composition)
442
+ }
430
443
 
431
444
  rule(:expression_comp) {
432
445
  solvens_line |
433
- multiple_et_line |
434
- label_id_composition |
435
- corresp_line_neu |
436
- leading_label.maybe >> space? >> composition.as(:composition) >> space? >> str('.').maybe >> space? |
437
- polvac |
438
- label_comment_excipiens |
439
- excipiens.as(:composition) |
440
- space.repeat(3)
446
+ multiple_et_line |
447
+ label_id_composition |
448
+ corresp_line_neu |
449
+ leading_label.maybe >> space? >> composition.as(:composition) >> space? >> str(".").maybe >> space? |
450
+ polvac |
451
+ label_comment_excipiens |
452
+ excipiens.as(:composition) |
453
+ space.repeat(3)
441
454
  }
442
455
 
443
456
  rule(:expression_compD) {
444
457
  solvens_line |
445
- multiple_et_line.as('multiple_et_line') |
446
- label_id_composition.as('label_id_composition') |
447
- corresp_line_neu.as('corresp_line_neu') |
448
- leading_label.maybe >> space? >> composition.as(:composition) >> space? >> str('.').maybe >> space? |
449
- polvac.as('polvac') |
450
- label_comment_excipiens.as('label_comment_excipiens') |
451
- excipiens.as(:composition) |
452
- space.repeat(3)
458
+ multiple_et_line.as("multiple_et_line") |
459
+ label_id_composition.as("label_id_composition") |
460
+ corresp_line_neu.as("corresp_line_neu") |
461
+ leading_label.maybe >> space? >> composition.as(:composition) >> space? >> str(".").maybe >> space? |
462
+ polvac.as("polvac") |
463
+ label_comment_excipiens.as("label_comment_excipiens") |
464
+ excipiens.as(:composition) |
465
+ space.repeat(3)
453
466
  }
454
467
 
455
468
  root :expression_comp
456
469
  end
457
470
 
458
471
  class GalenicFormParser < CompositionParser
472
+ rule(:prepation_separator) { str(", ") | str("\n") }
459
473
 
460
- rule(:prepation_separator) { str(', ') | str("\n") }
461
-
462
- rule(:prepation_name) { ((prepation_separator|lparen).absent? >> any).repeat(1)
463
- }
474
+ rule(:prepation_name) {
475
+ ((prepation_separator | lparen).absent? >> any).repeat(1)
476
+ }
464
477
  rule(:dose_with_pro) {
465
- ( match('[0-9a-zA-Z]').repeat(1) >>
466
- str('/') >>
467
- match('[0-9a-zA-Z\'%]').repeat(1)
468
- ).maybe
478
+ (match("[0-9a-zA-Z]").repeat(1) >>
479
+ str("/") >>
480
+ match("[0-9a-zA-Z'%]").repeat(1)
481
+ ).maybe
469
482
  }
470
483
 
471
484
  rule(:gal_form) {
472
485
  qty_unit_silent.maybe >>
473
- ((( str("\n") # |
474
- str(',') >> space? >> qty_unit_silent |
475
- digits >> str('%')
476
- ).absent? >> any).repeat(1) >>
477
- (lparen >> (rparen.absent? >> any).repeat(1) >> rparen).maybe
478
- ).as(:galenic_form) >>
479
- space?
480
-
486
+ (((str("\n") # |
487
+ str(",") >> space? >> qty_unit_silent |
488
+ digits >> str("%")
489
+ ).absent? >> any).repeat(1) >>
490
+ (lparen >> (rparen.absent? >> any).repeat(1) >> rparen).maybe
491
+ ).as(:galenic_form) >>
492
+ space?
481
493
  }
482
494
 
483
495
  rule(:standard_galenic) {
484
- prepation_name.as(:prepation_name) >> space? >>
485
- prepation_separator >> space? >>
486
- (name_without_parenthesis >> qty_unit_silent >> prepation_separator).maybe >>
487
- (qty_unit_silent >> space?).maybe >>
488
- (dose_with_pro >> space? >> str(',') >> space?).maybe >>
489
- gal_form >> space?
490
- }
491
-
492
- rule(:qty_unit_silent) { number >> space >> units }
493
- rule(:name_then_dose) { ((space.absent? >> any).repeat(1) >>
496
+ prepation_name.as(:prepation_name) >> space? >>
497
+ prepation_separator >> space? >>
498
+ (name_without_parenthesis >> qty_unit_silent >> prepation_separator).maybe >>
499
+ (qty_unit_silent >> space?).maybe >>
500
+ (dose_with_pro >> space? >> str(",") >> space?).maybe >>
501
+ gal_form >> space?
502
+ }
503
+
504
+ rule(:qty_unit_silent) { number >> space >> units }
505
+ rule(:name_then_dose) {
506
+ ((space.absent? >> any).repeat(1) >>
494
507
  space >> qty_unit_silent).as(:prepation_name) >> space?.as(:galenic_form)
495
- }
496
-
497
- rule(:only_name) { any.repeat(1).as(:prepation_name) >> space?.as(:galenic_form)
498
- }
499
-
500
- rule(:name_comma_gal_form) { (space.absent? >> any).repeat(1).as(:prepation_name) >>
501
- comma >> space >>
502
- any.repeat(1).as(:galenic_form)
503
- }
504
- rule(:simple_name) { ((match(["a-zA-Z0-9,%"]) | str('-') | umlaut).repeat(1)) >>
505
- (lparen >> (rparen.absent? >> any.repeat(1)) >> rparen).maybe
506
- }
508
+ }
509
+
510
+ rule(:only_name) {
511
+ any.repeat(1).as(:prepation_name) >> space?.as(:galenic_form)
512
+ }
513
+
514
+ rule(:name_comma_gal_form) {
515
+ (space.absent? >> any).repeat(1).as(:prepation_name) >>
516
+ comma >> space >>
517
+ any.repeat(1).as(:galenic_form)
518
+ }
519
+ rule(:simple_name) {
520
+ ((match(["a-zA-Z0-9,%"]) | str("-") | umlaut).repeat(1)) >>
521
+ (lparen >> (rparen.absent? >> any.repeat(1)) >> rparen).maybe
522
+ }
507
523
  rule(:name_gal_form) { # e.g. Dicloabak 0,1% Augentropfen or 35 Clear-Flex 3,86 % Peritonealdialyselösung
508
- (simple_name >> space).repeat(1).as(:prepation_name) >>
509
- space? >>
510
- (dose_with_pro >> space?).maybe >>
511
- (digits.absent? >> gal_form) >> space?
524
+ (simple_name >> space).repeat(1).as(:prepation_name) >>
525
+ space? >>
526
+ (dose_with_pro >> space?).maybe >>
527
+ (digits.absent? >> gal_form) >> space?
512
528
  }
513
529
 
514
530
  rule(:name_without_comma_gal_form) { # Sulfure de Rhénium (186Re)-RE-186-MM-1 Cis bio International
515
- ((str(', ')| str(',') >> match(['A-Z'])).absent? >> any).repeat(1).as(:prepation_name) >>
516
- comma >> space? >>
517
- gal_form >> space?
518
- }
519
-
520
- # Phytopharma foie et bile capsules/Leber-Galle Kapseln
521
- rule(:leber_gallen_kapseln) { ((str('/Leber-Galle Kapseln').absent? >> any).repeat(1)).as(:prepation_name) >>
522
- str('/') >> any.repeat(1).as(:galenic_form) >>
523
- space?
524
- }
525
- # Plak-out Spray 0,1 %
526
- rule(:plak_out_spray) { str('Plak-out Spray 0,1 %').as(:prepation_name) >>
527
- space? >> str('dummy').maybe.as(:galenic_form) >> space?
528
- }
529
- rule(:galenic) {
530
- plak_out_spray |
531
- leber_gallen_kapseln |
532
- standard_galenic |
533
- name_comma_gal_form |
534
- name_then_dose >> space? |
535
- name_without_comma_gal_form |
536
- name_gal_form |
537
- only_name >> space? |
538
- space?
539
- }
531
+ ((str(", ") | str(",") >> match(["A-Z"])).absent? >> any).repeat(1).as(:prepation_name) >>
532
+ comma >> space? >>
533
+ gal_form >> space?
534
+ }
535
+
536
+ # Phytopharma foie et bile capsules/Leber-Galle Kapseln
537
+ rule(:leber_gallen_kapseln) {
538
+ ((str("/Leber-Galle Kapseln").absent? >> any).repeat(1)).as(:prepation_name) >>
539
+ str("/") >> any.repeat(1).as(:galenic_form) >>
540
+ space?
541
+ }
542
+ # Plak-out Spray 0,1 %
543
+ rule(:plak_out_spray) {
544
+ str("Plak-out Spray 0,1 %").as(:prepation_name) >>
545
+ space? >> str("dummy").maybe.as(:galenic_form) >> space?
546
+ }
547
+ rule(:galenic) {
548
+ plak_out_spray |
549
+ leber_gallen_kapseln |
550
+ standard_galenic |
551
+ name_comma_gal_form |
552
+ name_then_dose >> space? |
553
+ name_without_comma_gal_form |
554
+ name_gal_form |
555
+ only_name >> space? |
556
+ space?
557
+ }
540
558
 
541
559
  # for debugging purposes only
542
- rule(:galenicD) {
543
- plak_out_spray.as(:plak_out_spray) |
544
- leber_gallen_kapseln.as(:leber_gallen_kapseln) |
545
- standard_galenic.as(:standard_galenic) |
546
- name_comma_gal_form.as(:name_comma_gal_form) |
547
- name_then_dose.as(:name_then_dose) >> space? |
548
- name_without_comma_gal_form.as(:name_without_comma_gal_form) |
549
- name_gal_form.as(:name_gal_form) |
550
- only_name.as(:only_name) >> space? |
551
- space?
552
- }
560
+ rule(:galenicD) {
561
+ plak_out_spray.as(:plak_out_spray) |
562
+ leber_gallen_kapseln.as(:leber_gallen_kapseln) |
563
+ standard_galenic.as(:standard_galenic) |
564
+ name_comma_gal_form.as(:name_comma_gal_form) |
565
+ name_then_dose.as(:name_then_dose) >> space? |
566
+ name_without_comma_gal_form.as(:name_without_comma_gal_form) |
567
+ name_gal_form.as(:name_gal_form) |
568
+ only_name.as(:only_name) >> space? |
569
+ space?
570
+ }
553
571
  root :galenic
554
- end
572
+ end