oddb2xml 2.7.1 → 2.7.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -2
- data/.standard.yml +2 -0
- data/Gemfile +3 -3
- data/History.txt +24 -0
- data/README.md +3 -3
- data/Rakefile +24 -23
- data/bin/check_artikelstamm +11 -11
- data/bin/compare_v5 +23 -23
- data/bin/oddb2xml +14 -13
- data/lib/oddb2xml/builder.rb +1070 -1038
- data/lib/oddb2xml/calc.rb +232 -233
- data/lib/oddb2xml/chapter_70_hack.rb +38 -32
- data/lib/oddb2xml/cli.rb +252 -236
- data/lib/oddb2xml/compare.rb +70 -59
- data/lib/oddb2xml/compositions_syntax.rb +451 -430
- data/lib/oddb2xml/compressor.rb +20 -20
- data/lib/oddb2xml/downloader.rb +157 -129
- data/lib/oddb2xml/extractor.rb +295 -295
- data/lib/oddb2xml/options.rb +34 -35
- data/lib/oddb2xml/parslet_compositions.rb +265 -269
- data/lib/oddb2xml/semantic_check.rb +39 -33
- data/lib/oddb2xml/util.rb +163 -163
- data/lib/oddb2xml/version.rb +1 -1
- data/lib/oddb2xml/xml_definitions.rb +32 -33
- data/lib/oddb2xml.rb +1 -1
- data/oddb2xml.gemspec +34 -34
- data/shell.nix +17 -0
- data/spec/artikelstamm_spec.rb +111 -110
- data/spec/builder_spec.rb +490 -505
- data/spec/calc_spec.rb +552 -593
- data/spec/check_artikelstamm_spec.rb +26 -26
- data/spec/cli_spec.rb +173 -174
- data/spec/compare_spec.rb +9 -11
- data/spec/composition_syntax_spec.rb +390 -409
- data/spec/compressor_spec.rb +48 -48
- data/spec/data/transfer.dat +1 -0
- data/spec/data_helper.rb +47 -49
- data/spec/downloader_spec.rb +251 -260
- data/spec/extractor_spec.rb +171 -159
- data/spec/fixtures/vcr_cassettes/oddb2xml.json +1 -1
- data/spec/galenic_spec.rb +233 -256
- data/spec/options_spec.rb +116 -119
- data/spec/parslet_spec.rb +896 -863
- data/spec/spec_helper.rb +153 -153
- data/test_options.rb +39 -42
- data/tools/win_fetch_cacerts.rb +2 -3
- metadata +42 -12
@@ -1,554 +1,575 @@
|
|
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
|
10
|
-
require
|
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)
|
17
|
-
rule(:rparen)
|
18
|
-
rule(:comma)
|
13
|
+
rule(:lparen) { str("(") }
|
14
|
+
rule(:rparen) { str(")") }
|
15
|
+
rule(:comma) { str(",") }
|
19
16
|
|
20
|
-
rule(:space)
|
21
|
-
rule(:space?)
|
17
|
+
rule(:space) { match('\s').repeat(1) }
|
18
|
+
rule(:space?) { space.maybe }
|
22
19
|
|
23
20
|
# Things
|
24
|
-
rule(:digit) { match(
|
21
|
+
rule(:digit) { match("[0-9]") }
|
25
22
|
rule(:digits) { digit.repeat(1) }
|
26
23
|
rule(:number) {
|
27
24
|
(
|
28
|
-
str(
|
29
|
-
str(
|
25
|
+
str("-").maybe >> (
|
26
|
+
str("0") | (match("[1-9]") >> match("[0-9']").repeat)
|
30
27
|
) >> (
|
31
|
-
(str(
|
32
|
-
(match([
|
33
|
-
|
34
|
-
match(
|
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) {
|
39
|
-
|
40
|
-
|
41
|
-
|
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[
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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(
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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(
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
}
|
77
|
-
rule(:identifier)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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[
|
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[
|
92
|
-
|
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[
|
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
|
-
|
101
|
-
str(
|
102
|
-
str(
|
103
|
-
str(
|
104
|
-
str(
|
105
|
-
str(
|
106
|
-
str(
|
107
|
-
str(
|
108
|
-
str(
|
109
|
-
str(
|
110
|
-
str(
|
111
|
-
str(
|
112
|
-
str(
|
113
|
-
str(
|
114
|
-
str(
|
115
|
-
str(
|
116
|
-
str(
|
117
|
-
str(
|
118
|
-
str(
|
119
|
-
str(
|
120
|
-
str(
|
121
|
-
str(
|
122
|
-
str(
|
123
|
-
str(
|
124
|
-
str(
|
125
|
-
str(
|
126
|
-
str(
|
127
|
-
str(
|
128
|
-
str(
|
129
|
-
str(
|
130
|
-
str(
|
131
|
-
str(
|
132
|
-
str(
|
133
|
-
str(
|
134
|
-
str(
|
135
|
-
str(
|
136
|
-
str(
|
137
|
-
str(
|
138
|
-
str(
|
139
|
-
str(
|
140
|
-
str(
|
141
|
-
str(
|
142
|
-
str(
|
143
|
-
str(
|
144
|
-
str(
|
145
|
-
str(
|
146
|
-
str(
|
147
|
-
str(
|
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)
|
152
|
-
rule(:qty_unit)
|
153
|
-
rule(:dose_qty)
|
154
|
-
rule(:min_max)
|
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(
|
157
|
-
rule(:dose_per) { (digits >> str(
|
158
|
-
rule(:dose)
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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) {
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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) {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
rule(:der_identifier) { str(
|
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
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
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 dosi") |
|
217
|
+
str("pro vitroe") |
|
218
|
+
str("q.s. ad ") |
|
219
|
+
str("q.s. pro ") |
|
220
|
+
str("ratio:") |
|
221
|
+
str("ut alia: ") |
|
222
|
+
str("ut ")
|
223
|
+
}
|
223
224
|
rule(:name_without_parenthesis) {
|
224
225
|
(
|
225
|
-
(str(
|
226
|
-
(radio_isotop | str(
|
226
|
+
(str("(") | forbidden_in_substance_name).absent? >>
|
227
|
+
(radio_isotop | str("> 1000") | str("> 500") | identifier.repeat(1) >> str(".").maybe) >>
|
227
228
|
space?
|
228
229
|
).repeat(1)
|
229
230
|
}
|
230
231
|
|
231
|
-
rule(:part_with_parenthesis) {
|
232
|
-
|
233
|
-
|
232
|
+
rule(:part_with_parenthesis) {
|
233
|
+
lparen >> ((lparen | rparen).absent? >> any).repeat(1) >>
|
234
|
+
(part_with_parenthesis | rparen >> str("-like:") | rparen) >> space?
|
235
|
+
}
|
234
236
|
rule(:name_with_parenthesis) {
|
235
237
|
forbidden_in_substance_name.absent? >>
|
236
|
-
|
237
|
-
|
238
|
+
((comma | lparen).absent? >> any).repeat(0) >> part_with_parenthesis >>
|
239
|
+
(forbidden_in_substance_name.absent? >> (identifier.repeat(1) | part_with_parenthesis | rparen) >> space?).repeat(0)
|
238
240
|
}
|
239
|
-
rule(:substance_name) {
|
241
|
+
rule(:substance_name) {
|
242
|
+
(
|
240
243
|
name_with_parenthesis |
|
241
244
|
name_without_parenthesis
|
242
245
|
) >>
|
243
|
-
|
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)
|
246
|
+
str("pro dosi").maybe >> space?
|
247
|
+
}
|
248
|
+
rule(:simple_substance) { substance_name.as(:substance_name) >> space? >> dose.maybe.as(:dose) }
|
249
|
+
rule(:simple_subtance_with_digits_in_name_and_dose) {
|
247
250
|
substance_lead.maybe.as(:more_info) >> space? >>
|
248
|
-
|
249
|
-
|
251
|
+
(name_without_parenthesis >> space? >> ((digits.repeat(1) >> (str(" %") | str("%")) | digits.repeat(1)))).as(:substance_name) >>
|
252
|
+
space >> dose_with_unit.as(:dose)
|
250
253
|
}
|
251
254
|
|
252
|
-
|
253
255
|
rule(:substance_more_info) { # e.g. "acari allergeni extractum 5000 U.:
|
254
|
-
|
255
|
-
|
256
|
+
(str("ratio:").absent? >> (identifier | digits) >> space?).repeat(1) >> space? >> (str("U.:") | str(":") | str(".:")) >> space?
|
257
|
+
}
|
256
258
|
|
257
259
|
rule(:pro_identifiers) {
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
rule(:
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
rule(:
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
260
|
+
str("ut aqua ad iniectabilia q.s. ad emulsionem pro ") |
|
261
|
+
str("aqua ").maybe >> str("ad iniectabile q.s. ad suspensionem pro ") |
|
262
|
+
str("aqua ").maybe >> str("ad iniectabile q.s. ad solutionem pro ") |
|
263
|
+
str("aqua ").maybe >> str("ad iniectabile ad solutionem pro ") |
|
264
|
+
str("aqua ").maybe >> str("ad iniectabilia q.s. ad solutionem pro ") |
|
265
|
+
str("aqua ").maybe >> str("ad solutionem pro ") |
|
266
|
+
str("aqua ").maybe >> str("q.s. ad emulsionem pro ") |
|
267
|
+
str("aqua ").maybe >> str("q.s. ad gelatume pro ") |
|
268
|
+
str("aqua ").maybe >> str("q.s. ad solutionem pro ") |
|
269
|
+
str("aqua ").maybe >> str("q.s. ad suspensionem pro ") |
|
270
|
+
str("doses pro vase ") |
|
271
|
+
str("excipiens ad emulsionem pro ") |
|
272
|
+
str("excipiens ad pulverem pro ") |
|
273
|
+
str("excipiens ad solutionem pro ") |
|
274
|
+
str("pro vase ") |
|
275
|
+
str("pro capsula ") |
|
276
|
+
str("q.s. ad pulverem pro ")
|
277
|
+
}
|
278
|
+
rule(:excipiens_dose) {
|
279
|
+
pro_identifiers.as(:excipiens_description) >> space? >> dose.as(:dose) >> space? >> ratio.maybe.as(:ratio) >>
|
280
|
+
space? >> str("corresp.").maybe >> space? >> dose.maybe.as(:dose_corresp)
|
281
|
+
}
|
282
|
+
|
283
|
+
rule(:excipiens_identifiers) {
|
284
|
+
str("ad globulos") |
|
285
|
+
str("ad pulverem") |
|
286
|
+
str("ad solutionem") |
|
287
|
+
str("aether q.s.") |
|
288
|
+
str("ana partes") |
|
289
|
+
str("aqua ad iniectabilia q.s. ad solutionem") |
|
290
|
+
str("aqua ad iniectabilia") |
|
291
|
+
str("aqua q.s. ad") |
|
292
|
+
str("excipiens pro compresso obducto") |
|
293
|
+
str("excipiens pro compresso") |
|
294
|
+
str("excipiens pro praeparatione") |
|
295
|
+
str("excipiens") |
|
296
|
+
str("pro charta") |
|
297
|
+
str("pro praeparatione") |
|
298
|
+
str("pro vitro") |
|
299
|
+
str("q.s. ad") |
|
300
|
+
str("q.s. pro praeparatione") |
|
301
|
+
str("saccharum ad") |
|
302
|
+
str("solvens (i.v.): aqua ad iniectabilia")
|
303
|
+
}
|
304
|
+
|
305
|
+
rule(:excipiens) {
|
306
|
+
substance_lead.maybe.as(:more_info) >> space? >>
|
307
|
+
(excipiens_dose | (excipiens_identifiers >> any.repeat(0)).as(:excipiens_description)) >>
|
308
|
+
any.repeat(0)
|
309
|
+
}
|
310
|
+
|
311
|
+
rule(:substance_lead) {
|
312
|
+
useage >> space? |
|
313
|
+
str("Beutel:") >> space? |
|
314
|
+
str("residui:") >> space? |
|
315
|
+
str("mineralia:") >> str(":") >> space? |
|
316
|
+
str("Solvens:") >> space? |
|
317
|
+
substance_more_info
|
318
|
+
}
|
310
319
|
rule(:corresp_substance_label) {
|
311
|
-
|
312
|
-
str(
|
313
|
-
str(
|
314
|
-
str(
|
315
|
-
str(
|
316
|
-
|
317
|
-
rule(:ratio) { str(
|
318
|
-
|
319
|
-
rule(:solvens) {
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
320
|
+
str(", corresp. ca.,") |
|
321
|
+
str("corresp. ca.,") |
|
322
|
+
str("corresp.,") |
|
323
|
+
str("corresp.") |
|
324
|
+
str(", corresp.")
|
325
|
+
}
|
326
|
+
rule(:ratio) { str("ratio:") >> space >> ratio_value }
|
327
|
+
|
328
|
+
rule(:solvens) {
|
329
|
+
(str("Solvens:") | str("Solvens (i.m.):")) >> space >> (any.repeat).as(:more_info) >> space? >>
|
330
|
+
(substance.as(:substance) >> str("/L").maybe).maybe >>
|
331
|
+
any.maybe
|
332
|
+
}
|
333
|
+
# Perhaps we could have some syntax sugar to make this more easy?
|
334
|
+
#
|
335
|
+
def tag(opts = {})
|
336
|
+
opts[:close] || false
|
337
|
+
end
|
338
|
+
|
339
|
+
# TODO: what does ut alia: impl?
|
330
340
|
rule(:substance_ut) {
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
341
|
+
(space? >> (str("pro dosi ut ") | str("ut ")) >>
|
342
|
+
space? >> str("alia:").absent? >> substance
|
343
|
+
) >>
|
344
|
+
space?
|
345
|
+
}
|
336
346
|
|
337
347
|
rule(:corresp_substance) {
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
348
|
+
(corresp_substance_label) >> space? >>
|
349
|
+
(
|
350
|
+
substance |
|
351
|
+
dose.as(:dose_corresp_2) |
|
352
|
+
excipiens.as(:excipiens)
|
353
|
+
)
|
344
354
|
}
|
345
355
|
|
346
356
|
rule(:substance) {
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
(space? >> str(
|
357
|
+
(
|
358
|
+
simple_subtance_with_digits_in_name_and_dose |
|
359
|
+
der |
|
360
|
+
substance_lead.maybe.as(:more_info) >> space? >> lebensmittel_zusatz |
|
361
|
+
substance_lead.maybe.as(:more_info) >> space? >> simple_substance >> str("pro dosi").maybe
|
362
|
+
).as(:substance) >>
|
363
|
+
(space? >> str(", ").maybe >> ratio.maybe).as(:ratio) >>
|
354
364
|
space? >> corresp_substance.maybe.as(:chemical_substance) >>
|
355
365
|
space? >> substance_ut.repeat(0).as(:substance_ut)
|
356
366
|
}
|
357
|
-
rule(:histamin) { str(
|
358
|
-
rule(:praeparatio){
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
rule(:
|
365
|
-
rule(:
|
366
|
-
rule(:
|
367
|
+
rule(:histamin) { str("U = Histamin Equivalent Prick").as(:histamin) }
|
368
|
+
rule(:praeparatio) {
|
369
|
+
((one_word >> space?).repeat(1).as(:description) >> str(":") >> space?).maybe >>
|
370
|
+
(name_with_parenthesis | name_without_parenthesis).repeat(1).as(:substance_name) >>
|
371
|
+
number.as(:qty) >> space >> str("U.:") >> space? >>
|
372
|
+
((identifier >> space?).repeat(1).as(:more_info) >> space?).maybe
|
373
|
+
}
|
374
|
+
rule(:substance_separator) { (str(", et ") | comma | str("et ") | str("ut alia: ")) >> space? }
|
375
|
+
rule(:one_substance) { (praeparatio | histamin | substance) >> space? >> ratio.as(:ratio).maybe >> space? }
|
376
|
+
rule(:all_substances) { (one_substance >> substance_separator.maybe).repeat(1) >> space? >> excipiens.as(:excipiens).maybe }
|
377
|
+
rule(:composition) { all_substances }
|
367
378
|
rule(:long_labels) {
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
379
|
+
str("Praeparatio sicca cum solvens: praeparatio sicca:") |
|
380
|
+
str("Praeparatio cryodesiccata") >> (str(":").absent? >> any).repeat(0) >> str(":") |
|
381
|
+
str("Tela cum praeparatione (Panel ") >> digit >> str("):")
|
382
|
+
}
|
372
383
|
rule(:label_id) {
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
+
(
|
385
|
+
str("V") |
|
386
|
+
str("IV") |
|
387
|
+
str("III") |
|
388
|
+
str("II") |
|
389
|
+
str("I") |
|
390
|
+
str("A") |
|
391
|
+
str("B") |
|
392
|
+
str("C") |
|
393
|
+
str("D") |
|
394
|
+
str("E")
|
384
395
|
)
|
385
396
|
}
|
386
|
-
rule(:label_separator) {
|
387
|
-
rule(:label) {
|
388
|
-
|
389
|
-
|
397
|
+
rule(:label_separator) { (str("):") | str(")")) }
|
398
|
+
rule(:label) {
|
399
|
+
label_id.as(:label) >> space? >>
|
400
|
+
label_separator >> str(",").absent? >>
|
401
|
+
(space? >> (match(/[^:]/).repeat(0)).as(:label_description) >> str(":") >> space).maybe
|
402
|
+
}
|
403
|
+
rule(:leading_label) {
|
404
|
+
label_id >> label_separator >> (str(" et ") | str(", ") | str(" pro usu: ") | space) >>
|
405
|
+
label_id >> label_separator >> any.repeat(1) |
|
406
|
+
long_labels.as(:label) |
|
407
|
+
label
|
390
408
|
}
|
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
409
|
rule(:corresp_label) {
|
397
|
-
str(
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
}
|
407
|
-
rule(:corresp_line) {
|
408
|
-
|
409
|
-
|
410
|
+
str("aqua ") |
|
411
|
+
str("excipiens ") |
|
412
|
+
str("doses ") |
|
413
|
+
str("Pulver: ") |
|
414
|
+
str("Diluens: ") |
|
415
|
+
str("Solutio reconstituta:") |
|
416
|
+
str("Corresp., ") |
|
417
|
+
str("Corresp. ") |
|
418
|
+
str("corresp. ")
|
419
|
+
}
|
420
|
+
rule(:corresp_line) {
|
421
|
+
corresp_label >> any.repeat(1).as(:corresp) |
|
422
|
+
((label_id >> label_separator >> space? >> str("et ").maybe).repeat(1) >> any.repeat(1)).as(:corresp)
|
423
|
+
}
|
410
424
|
rule(:corresp_line_neu) { corresp_label >> any.repeat(1).as(:corresp) }
|
411
425
|
|
412
426
|
rule(:solvens_label) {
|
413
|
-
str(
|
414
|
-
|
415
|
-
|
427
|
+
str("Solvens (i.v.)") |
|
428
|
+
str("Solvens (i.m.)") |
|
429
|
+
str("Solvens")
|
416
430
|
}
|
417
|
-
rule(:solvens_line) { solvens_label.as(:label) >> (str(
|
431
|
+
rule(:solvens_line) { solvens_label.as(:label) >> (str(": ") >> composition.repeat(1).as(:composition) | any.repeat(1).as(:corresp)) }
|
418
432
|
|
419
433
|
rule(:multiple_et_line) {
|
420
|
-
|
434
|
+
((label_id >> label_separator >> space? >> (str("pro usu") | str("et "))).repeat(1) >> any.repeat(1)).as(:corresp)
|
421
435
|
}
|
422
436
|
|
423
|
-
rule(:polvac) { label_id.as(:label) >> label_separator >> space? >> composition.as(:composition) >> space? >> str(
|
437
|
+
rule(:polvac) { label_id.as(:label) >> label_separator >> space? >> composition.as(:composition) >> space? >> str(".").maybe >> space? }
|
424
438
|
|
425
|
-
rule(:label_comment_excipiens) { label >> space? >> excipiens.as(:excipiens) >> space? >> str(
|
439
|
+
rule(:label_comment_excipiens) { label >> space? >> excipiens.as(:excipiens) >> space? >> str(".").maybe >> space? }
|
426
440
|
|
427
|
-
rule(:label_id_composition) {
|
428
|
-
|
429
|
-
|
441
|
+
rule(:label_id_composition) {
|
442
|
+
label_id.as(:label) >> label_separator >>
|
443
|
+
((space >> identifier).repeat(1) >> str(":")).maybe.as(:label_description) >>
|
444
|
+
composition.as(:composition)
|
445
|
+
}
|
430
446
|
|
431
447
|
rule(:expression_comp) {
|
432
448
|
solvens_line |
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
449
|
+
multiple_et_line |
|
450
|
+
label_id_composition |
|
451
|
+
corresp_line_neu |
|
452
|
+
leading_label.maybe >> space? >> composition.as(:composition) >> space? >> str(".").maybe >> space? |
|
453
|
+
polvac |
|
454
|
+
label_comment_excipiens |
|
455
|
+
excipiens.as(:composition) |
|
456
|
+
space.repeat(3)
|
441
457
|
}
|
442
458
|
|
443
459
|
rule(:expression_compD) {
|
444
460
|
solvens_line |
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
461
|
+
multiple_et_line.as("multiple_et_line") |
|
462
|
+
label_id_composition.as("label_id_composition") |
|
463
|
+
corresp_line_neu.as("corresp_line_neu") |
|
464
|
+
leading_label.maybe >> space? >> composition.as(:composition) >> space? >> str(".").maybe >> space? |
|
465
|
+
polvac.as("polvac") |
|
466
|
+
label_comment_excipiens.as("label_comment_excipiens") |
|
467
|
+
excipiens.as(:composition) |
|
468
|
+
space.repeat(3)
|
453
469
|
}
|
454
470
|
|
455
471
|
root :expression_comp
|
456
472
|
end
|
457
473
|
|
458
474
|
class GalenicFormParser < CompositionParser
|
475
|
+
rule(:prepation_separator) { str(", ") | str("\n") }
|
459
476
|
|
460
|
-
rule(:
|
461
|
-
|
462
|
-
|
463
|
-
}
|
477
|
+
rule(:prepation_name) {
|
478
|
+
((prepation_separator | lparen).absent? >> any).repeat(1)
|
479
|
+
}
|
464
480
|
rule(:dose_with_pro) {
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
481
|
+
(match("[0-9a-zA-Z]").repeat(1) >>
|
482
|
+
str("/") >>
|
483
|
+
match("[0-9a-zA-Z'%]").repeat(1)
|
484
|
+
).maybe
|
469
485
|
}
|
470
486
|
|
471
487
|
rule(:gal_form) {
|
472
488
|
qty_unit_silent.maybe >>
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
489
|
+
(((str("\n") # |
|
490
|
+
str(",") >> space? >> qty_unit_silent |
|
491
|
+
digits >> str("%")
|
492
|
+
).absent? >> any).repeat(1) >>
|
493
|
+
(lparen >> (rparen.absent? >> any).repeat(1) >> rparen).maybe
|
494
|
+
).as(:galenic_form) >>
|
495
|
+
space?
|
481
496
|
}
|
482
497
|
|
483
498
|
rule(:standard_galenic) {
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
rule(:qty_unit_silent) { number >> space >> units
|
493
|
-
rule(:name_then_dose) {
|
499
|
+
prepation_name.as(:prepation_name) >> space? >>
|
500
|
+
prepation_separator >> space? >>
|
501
|
+
(name_without_parenthesis >> qty_unit_silent >> prepation_separator).maybe >>
|
502
|
+
(qty_unit_silent >> space?).maybe >>
|
503
|
+
(dose_with_pro >> space? >> str(",") >> space?).maybe >>
|
504
|
+
gal_form >> space?
|
505
|
+
}
|
506
|
+
|
507
|
+
rule(:qty_unit_silent) { number >> space >> units }
|
508
|
+
rule(:name_then_dose) {
|
509
|
+
((space.absent? >> any).repeat(1) >>
|
494
510
|
space >> qty_unit_silent).as(:prepation_name) >> space?.as(:galenic_form)
|
495
|
-
|
496
|
-
|
497
|
-
rule(:only_name) {
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
511
|
+
}
|
512
|
+
|
513
|
+
rule(:only_name) {
|
514
|
+
any.repeat(1).as(:prepation_name) >> space?.as(:galenic_form)
|
515
|
+
}
|
516
|
+
|
517
|
+
rule(:name_comma_gal_form) {
|
518
|
+
(space.absent? >> any).repeat(1).as(:prepation_name) >>
|
519
|
+
comma >> space >>
|
520
|
+
any.repeat(1).as(:galenic_form)
|
521
|
+
}
|
522
|
+
rule(:simple_name) {
|
523
|
+
((match(["a-zA-Z0-9,%"]) | str("-") | umlaut).repeat(1)) >>
|
524
|
+
(lparen >> (rparen.absent? >> any.repeat(1)) >> rparen).maybe
|
525
|
+
}
|
507
526
|
rule(:name_gal_form) { # e.g. Dicloabak 0,1% Augentropfen or 35 Clear-Flex 3,86 % Peritonealdialyselösung
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
527
|
+
(simple_name >> space).repeat(1).as(:prepation_name) >>
|
528
|
+
space? >>
|
529
|
+
(dose_with_pro >> space?).maybe >>
|
530
|
+
(digits.absent? >> gal_form) >> space?
|
512
531
|
}
|
513
532
|
|
514
533
|
rule(:name_without_comma_gal_form) { # Sulfure de Rhénium (186Re)-RE-186-MM-1 Cis bio International
|
515
|
-
((str(
|
516
|
-
|
517
|
-
|
518
|
-
}
|
519
|
-
|
520
|
-
# Phytopharma foie et bile capsules/Leber-Galle Kapseln
|
521
|
-
rule(:leber_gallen_kapseln) {
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
534
|
+
((str(", ") | str(",") >> match(["A-Z"])).absent? >> any).repeat(1).as(:prepation_name) >>
|
535
|
+
comma >> space? >>
|
536
|
+
gal_form >> space?
|
537
|
+
}
|
538
|
+
|
539
|
+
# Phytopharma foie et bile capsules/Leber-Galle Kapseln
|
540
|
+
rule(:leber_gallen_kapseln) {
|
541
|
+
((str("/Leber-Galle Kapseln").absent? >> any).repeat(1)).as(:prepation_name) >>
|
542
|
+
str("/") >> any.repeat(1).as(:galenic_form) >>
|
543
|
+
space?
|
544
|
+
}
|
545
|
+
# Plak-out Spray 0,1 %
|
546
|
+
rule(:plak_out_spray) {
|
547
|
+
str("Plak-out Spray 0,1 %").as(:prepation_name) >>
|
548
|
+
space? >> str("dummy").maybe.as(:galenic_form) >> space?
|
549
|
+
}
|
550
|
+
rule(:galenic) {
|
551
|
+
plak_out_spray |
|
552
|
+
leber_gallen_kapseln |
|
553
|
+
standard_galenic |
|
554
|
+
name_comma_gal_form |
|
555
|
+
name_then_dose >> space? |
|
556
|
+
name_without_comma_gal_form |
|
557
|
+
name_gal_form |
|
558
|
+
only_name >> space? |
|
559
|
+
space?
|
560
|
+
}
|
540
561
|
|
541
562
|
# for debugging purposes only
|
542
|
-
rule(:galenicD)
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
563
|
+
rule(:galenicD) {
|
564
|
+
plak_out_spray.as(:plak_out_spray) |
|
565
|
+
leber_gallen_kapseln.as(:leber_gallen_kapseln) |
|
566
|
+
standard_galenic.as(:standard_galenic) |
|
567
|
+
name_comma_gal_form.as(:name_comma_gal_form) |
|
568
|
+
name_then_dose.as(:name_then_dose) >> space? |
|
569
|
+
name_without_comma_gal_form.as(:name_without_comma_gal_form) |
|
570
|
+
name_gal_form.as(:name_gal_form) |
|
571
|
+
only_name.as(:only_name) >> space? |
|
572
|
+
space?
|
573
|
+
}
|
553
574
|
root :galenic
|
554
|
-
end
|
575
|
+
end
|