drgdsl 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/bin/cache +63 -0
- data/bin/html +2 -0
- data/lib/drgdsl/ast.rb +105 -16
- data/lib/drgdsl/parser.rb +1 -1
- data/lib/drgdsl/pretty_printer.rb +14 -0
- data/lib/drgdsl/version.rb +1 -1
- data/lib/drgdsl/visitor.rb +43 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 346dd382500a954f17d93e1d1385e6cb8af10b02059298776973f0af8389686d
|
4
|
+
data.tar.gz: 3add8eaaa026e2bd054c230933be1e546592da9c919b67155e35165025a89e5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7fda718baaaa0077ed81705b6178a11b8ba8d170b19d53aa7b4fc61d1ed86f18514ec153422b9406d4b429b5d53f467fb91e92dec3e4289d2ded36f1b6eae5f
|
7
|
+
data.tar.gz: '00138b8f522e3c277163a86724a011e92e83845aae9a9fd6fdf67921b7f0bc7dde2030de8f78ed80bf4756dd2765a109057e1a41e724e8333fe907dd2394ec31'
|
data/Gemfile.lock
CHANGED
data/bin/cache
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require "bundler/setup"
|
6
|
+
require "drgdsl"
|
7
|
+
require 'benchmark'
|
8
|
+
|
9
|
+
string_printer = DrgDSL::PrettyPrinter.new(output_format: :string)
|
10
|
+
html_printer = DrgDSL::PrettyPrinter.new(output_format: :html)
|
11
|
+
bash_printer = DrgDSL::PrettyPrinter.new(output_format: :bash)
|
12
|
+
|
13
|
+
asts = File.read('./test/expressions.txt', encoding: 'utf-8')
|
14
|
+
.split("\n\n")
|
15
|
+
.map { |exp| DrgDSL.parse(exp) }
|
16
|
+
|
17
|
+
N = 2
|
18
|
+
|
19
|
+
puts "Pretty printing #{N} * #{asts.count} ASTs:"
|
20
|
+
|
21
|
+
t1 = Benchmark.realtime do
|
22
|
+
N.times do
|
23
|
+
asts.each do |ast|
|
24
|
+
ast.accept(string_printer)
|
25
|
+
ast.accept(html_printer)
|
26
|
+
ast.accept(bash_printer)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
puts "PrettyPrinter while building up cache: \t#{t1}"
|
31
|
+
|
32
|
+
t2 = Benchmark.realtime do
|
33
|
+
N.times do
|
34
|
+
asts.each do |ast|
|
35
|
+
ast.accept(string_printer)
|
36
|
+
ast.accept(html_printer)
|
37
|
+
ast.accept(bash_printer)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
puts "PrettyPrinter with cache hits only: \t#{t2}"
|
42
|
+
|
43
|
+
[string_printer, html_printer, bash_printer].each do |printer|
|
44
|
+
class << printer
|
45
|
+
def cache?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
t3 = Benchmark.realtime do
|
52
|
+
N.times do
|
53
|
+
asts.each do |ast|
|
54
|
+
ast.accept(string_printer)
|
55
|
+
ast.accept(html_printer)
|
56
|
+
ast.accept(bash_printer)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
puts "PrettyPrinter with caching disabled: \t#{t3}"
|
61
|
+
|
62
|
+
puts "Speed increase when enabling caching: \t#{(100 / t3 * (t3 - t1)).round(2)}%"
|
63
|
+
puts "Speed increase when cache fully built up: \t#{(100 / t3 * (t3 - t2)).round(2)}%"
|
data/bin/html
CHANGED
data/lib/drgdsl/ast.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DrgDSL
|
2
4
|
|
3
5
|
# Nodes in DRG logic AST.
|
4
6
|
#
|
5
7
|
# @see AstBuilder
|
6
8
|
module Ast
|
9
|
+
def self.node_classes
|
10
|
+
Node.node_classes
|
11
|
+
end
|
12
|
+
|
7
13
|
module Node
|
8
14
|
class << self
|
9
15
|
def node_classes
|
@@ -46,6 +52,19 @@ module DrgDSL
|
|
46
52
|
raise NotImplementedError
|
47
53
|
end
|
48
54
|
|
55
|
+
# @return [Integer] object hash for this AST node. Node instances for the
|
56
|
+
# same expression should always return the same hash code. This is
|
57
|
+
# useful for optimizations.
|
58
|
+
def hash
|
59
|
+
raise NotImplementedError
|
60
|
+
end
|
61
|
+
|
62
|
+
def ==(other)
|
63
|
+
type == other.type && hash == other.hash
|
64
|
+
end
|
65
|
+
|
66
|
+
alias eql? ==
|
67
|
+
|
49
68
|
def pretty_print(**pretty_printer_options)
|
50
69
|
accept PrettyPrinter.new(**pretty_printer_options)
|
51
70
|
end
|
@@ -79,6 +98,10 @@ module DrgDSL
|
|
79
98
|
def to_hash
|
80
99
|
{ or: [expressions.map(&:to_hash)] }
|
81
100
|
end
|
101
|
+
|
102
|
+
def hash
|
103
|
+
@hash ||= [type, *expressions].hash
|
104
|
+
end
|
82
105
|
end
|
83
106
|
|
84
107
|
# Represents a list of expressions joined with an "AND",
|
@@ -93,7 +116,11 @@ module DrgDSL
|
|
93
116
|
end
|
94
117
|
|
95
118
|
def to_hash
|
96
|
-
{ and: [
|
119
|
+
{ and: [expressions.map(&:to_hash)] }
|
120
|
+
end
|
121
|
+
|
122
|
+
def hash
|
123
|
+
@hash ||= [type, *expressions].hash
|
97
124
|
end
|
98
125
|
end
|
99
126
|
|
@@ -110,6 +137,10 @@ module DrgDSL
|
|
110
137
|
def to_hash
|
111
138
|
{ paren: expression.to_hash }
|
112
139
|
end
|
140
|
+
|
141
|
+
def hash
|
142
|
+
@hash ||= [type, expression].hash
|
143
|
+
end
|
113
144
|
end
|
114
145
|
|
115
146
|
# A NotExpression is a logic text of the form
|
@@ -126,6 +157,10 @@ module DrgDSL
|
|
126
157
|
def to_hash
|
127
158
|
{ not: expression.to_hash }
|
128
159
|
end
|
160
|
+
|
161
|
+
def hash
|
162
|
+
@hash ||= [type, expression].hash
|
163
|
+
end
|
129
164
|
end
|
130
165
|
|
131
166
|
# "Komplizierende_Prozeduren", "Dialyse", ...
|
@@ -141,6 +176,10 @@ module DrgDSL
|
|
141
176
|
def to_hash
|
142
177
|
{ function_call: name }
|
143
178
|
end
|
179
|
+
|
180
|
+
def hash
|
181
|
+
@hash ||= [type, name].hash
|
182
|
+
end
|
144
183
|
end
|
145
184
|
|
146
185
|
# A drg link originates from the grammar rule basic_or_drg_link
|
@@ -160,6 +199,10 @@ module DrgDSL
|
|
160
199
|
def to_hash
|
161
200
|
{ drg_link: { var: variable.to_hash, name: name } }
|
162
201
|
end
|
202
|
+
|
203
|
+
def hash
|
204
|
+
@hash ||= [type, name, variable].hash
|
205
|
+
end
|
163
206
|
end
|
164
207
|
|
165
208
|
# A BasicExpression consists of a variable and a condition
|
@@ -187,9 +230,14 @@ module DrgDSL
|
|
187
230
|
def to_hash
|
188
231
|
{ basic: { var: variable.to_hash, condition: condition.to_hash } }
|
189
232
|
end
|
233
|
+
|
234
|
+
def hash
|
235
|
+
@hash ||= [type, variable, condition].hash
|
236
|
+
end
|
190
237
|
end
|
191
238
|
|
192
|
-
# A comparison is either from a table_condition, a condition or a
|
239
|
+
# A comparison is either from a table_condition, a condition or a
|
240
|
+
# date_expression
|
193
241
|
class Comparison
|
194
242
|
include Node
|
195
243
|
|
@@ -210,6 +258,10 @@ module DrgDSL
|
|
210
258
|
}
|
211
259
|
}
|
212
260
|
end
|
261
|
+
|
262
|
+
def hash
|
263
|
+
@hash ||= [type, op, value, table_condition].hash
|
264
|
+
end
|
213
265
|
end
|
214
266
|
|
215
267
|
# Has a certain operator (i.e. not / different) and a condition
|
@@ -227,13 +279,17 @@ module DrgDSL
|
|
227
279
|
end
|
228
280
|
|
229
281
|
def to_hash
|
230
|
-
{
|
282
|
+
{
|
231
283
|
unary_condition: {
|
232
284
|
op: op,
|
233
285
|
condition: condition.to_hash
|
234
286
|
}
|
235
287
|
}
|
236
288
|
end
|
289
|
+
|
290
|
+
def hash
|
291
|
+
@hash ||= [type, op, condition].hash
|
292
|
+
end
|
237
293
|
end
|
238
294
|
|
239
295
|
class Empty
|
@@ -242,15 +298,21 @@ module DrgDSL
|
|
242
298
|
def to_hash
|
243
299
|
{ empty: nil }
|
244
300
|
end
|
301
|
+
|
302
|
+
def hash
|
303
|
+
@hash ||= type.hash
|
304
|
+
end
|
245
305
|
end
|
246
306
|
|
247
|
-
# There are 3 variants of table conditions (in_table, in_tables,
|
248
|
-
#
|
249
|
-
#
|
307
|
+
# There are 3 variants of table conditions (in_table, in_tables,
|
308
|
+
# all_in_table)
|
309
|
+
#
|
310
|
+
# A table condition can have an optional comparison. Tables refers to the
|
311
|
+
# table names (the internal names)
|
250
312
|
class TableCondition
|
251
|
-
IN_TABLE = 'in table'
|
252
|
-
IN_TABLES = 'in tables'
|
253
|
-
ALL_IN_TABLE = 'all in table'
|
313
|
+
IN_TABLE = 'in table'
|
314
|
+
IN_TABLES = 'in tables'
|
315
|
+
ALL_IN_TABLE = 'all in table'
|
254
316
|
|
255
317
|
include Node
|
256
318
|
|
@@ -273,6 +335,10 @@ module DrgDSL
|
|
273
335
|
}
|
274
336
|
}
|
275
337
|
end
|
338
|
+
|
339
|
+
def hash
|
340
|
+
@hash ||= [type, op, *tables, comparison].hash
|
341
|
+
end
|
276
342
|
end
|
277
343
|
|
278
344
|
# INFO: srg (prozedur) l (links) r (rechts) b(beidseitig)
|
@@ -294,17 +360,21 @@ module DrgDSL
|
|
294
360
|
}
|
295
361
|
}
|
296
362
|
end
|
363
|
+
|
364
|
+
def hash
|
365
|
+
@hash ||= [type, variable, condition].hash
|
366
|
+
end
|
297
367
|
end
|
298
368
|
|
299
369
|
class DateExpression
|
300
370
|
include Node
|
301
371
|
|
302
372
|
attr_reader :left_variable,
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
373
|
+
:right_variable,
|
374
|
+
:left_condition,
|
375
|
+
:right_condition,
|
376
|
+
:comparison,
|
377
|
+
:opd
|
308
378
|
|
309
379
|
# @param opd [String] E.g. "opd4" => "mind. 4 erfüllen" query
|
310
380
|
def initialize(left_variable:,
|
@@ -312,8 +382,7 @@ module DrgDSL
|
|
312
382
|
left_condition:,
|
313
383
|
right_condition: nil,
|
314
384
|
comparison:,
|
315
|
-
opd:
|
316
|
-
)
|
385
|
+
opd:)
|
317
386
|
|
318
387
|
@left_variable = left_variable
|
319
388
|
@right_variable = right_variable
|
@@ -335,6 +404,18 @@ module DrgDSL
|
|
335
404
|
}
|
336
405
|
}
|
337
406
|
end
|
407
|
+
|
408
|
+
def hash
|
409
|
+
@hash ||= [
|
410
|
+
type,
|
411
|
+
left_variable,
|
412
|
+
right_variable,
|
413
|
+
left_condition,
|
414
|
+
right_condition,
|
415
|
+
comparison,
|
416
|
+
opd
|
417
|
+
].hash
|
418
|
+
end
|
338
419
|
end
|
339
420
|
|
340
421
|
# "PDX", "AGEYEARS", ...
|
@@ -350,6 +431,10 @@ module DrgDSL
|
|
350
431
|
def to_hash
|
351
432
|
{ name: name }
|
352
433
|
end
|
434
|
+
|
435
|
+
def hash
|
436
|
+
@hash ||= [type, name].hash
|
437
|
+
end
|
353
438
|
end
|
354
439
|
|
355
440
|
# "3", "'MDC'", ...
|
@@ -369,6 +454,10 @@ module DrgDSL
|
|
369
454
|
def to_hash
|
370
455
|
{ constant: { value: value } }
|
371
456
|
end
|
457
|
+
|
458
|
+
def hash
|
459
|
+
@hash ||= [type, value].hash
|
460
|
+
end
|
372
461
|
end
|
373
462
|
end
|
374
463
|
end
|
data/lib/drgdsl/parser.rb
CHANGED
@@ -52,6 +52,20 @@ module DrgDSL
|
|
52
52
|
''
|
53
53
|
end
|
54
54
|
|
55
|
+
def cache?
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def cache_key(n)
|
60
|
+
[
|
61
|
+
n.hash,
|
62
|
+
@indentation_level,
|
63
|
+
@indentation_string,
|
64
|
+
@output_format,
|
65
|
+
@multiline
|
66
|
+
].hash
|
67
|
+
end
|
68
|
+
|
55
69
|
private
|
56
70
|
|
57
71
|
def visit_Expression(n)
|
data/lib/drgdsl/version.rb
CHANGED
data/lib/drgdsl/visitor.rb
CHANGED
@@ -1,9 +1,52 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DrgDSL
|
4
|
+
|
4
5
|
# Mixin for Ast::Node visitors. Visits all child nodes and returns the
|
5
6
|
# visited node by default.
|
6
7
|
module Visitor
|
8
|
+
def self.included(visitor)
|
9
|
+
visitor.prepend Cache
|
10
|
+
visitor.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module Cache
|
14
|
+
# @param n [Ast::Node]
|
15
|
+
def visit(n)
|
16
|
+
return super(n) unless cache?
|
17
|
+
self.class.cache[cache_key(n)] ||= super(n)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
# @return [Hash] in-memory Ruby Hash
|
23
|
+
def cache
|
24
|
+
@cache ||= {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear_cache!
|
28
|
+
@cache = {}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Whether this visitor should cache visit results. Note that one might need
|
33
|
+
# to override #cache_key(n) if a visit is not deterministic, e.g. when it
|
34
|
+
# depends on some instance variables.
|
35
|
+
#
|
36
|
+
# @see PrettyPrinter#cache_key
|
37
|
+
#
|
38
|
+
# @return [Boolean]
|
39
|
+
def cache?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param n [Ast::Node]
|
44
|
+
# @return [Integer] ideally an object hash
|
45
|
+
def cache_key(n)
|
46
|
+
n.hash
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param n [Ast::Node]
|
7
50
|
def visit(n)
|
8
51
|
return visit_nil if n.nil?
|
9
52
|
send("visit_#{n.type}", n)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: drgdsl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SwissDRG AG
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -138,6 +138,7 @@ files:
|
|
138
138
|
- LICENSE.txt
|
139
139
|
- README.md
|
140
140
|
- Rakefile
|
141
|
+
- bin/cache
|
141
142
|
- bin/console
|
142
143
|
- bin/html
|
143
144
|
- bin/setup
|