oddb2xml 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
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