tdparser 1.5.1 → 1.6.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README +5 -0
- data/Rakefile +4 -0
- data/lib/tdparser/action_parser.rb +29 -0
- data/lib/tdparser/any_parser.rb +20 -0
- data/lib/tdparser/backref_parser.rb +29 -0
- data/lib/tdparser/buffer_utils.rb +13 -0
- data/lib/tdparser/choice_parser.rb +80 -0
- data/lib/tdparser/composite_parser.rb +29 -0
- data/lib/tdparser/concat_parser.rb +21 -0
- data/lib/tdparser/condition_parser.rb +28 -0
- data/lib/tdparser/empty_parser.rb +15 -0
- data/lib/tdparser/fail_parser.rb +15 -0
- data/lib/tdparser/grammar.rb +23 -0
- data/lib/tdparser/iteration_parser.rb +73 -0
- data/lib/tdparser/label_parser.rb +25 -0
- data/lib/tdparser/negative_parser.rb +17 -0
- data/lib/tdparser/non_terminal_parser.rb +33 -0
- data/lib/tdparser/none_parser.rb +18 -0
- data/lib/tdparser/parallel_parser.rb +18 -0
- data/lib/tdparser/parser.rb +104 -0
- data/lib/tdparser/reference_parser.rb +23 -0
- data/lib/tdparser/sequence.rb +7 -0
- data/lib/tdparser/stack_parser.rb +29 -0
- data/lib/tdparser/stackref_parser.rb +29 -0
- data/lib/tdparser/state_parser.rb +28 -0
- data/lib/tdparser/terminal_parser.rb +28 -0
- data/lib/tdparser/token_buffer.rb +43 -0
- data/lib/tdparser/token_generator.rb +43 -0
- data/lib/tdparser/utils.rb +3 -3
- data/lib/tdparser/version.rb +1 -1
- data/lib/tdparser/xml.rb +13 -11
- data/lib/tdparser.rb +45 -799
- data/sig/tdparser.rbs +334 -0
- data/updoc +11 -0
- metadata +32 -4
data/lib/tdparser.rb
CHANGED
@@ -5,782 +5,38 @@
|
|
5
5
|
# Top-down parser for embedded in a ruby script.
|
6
6
|
#
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
false
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_a
|
38
|
-
@enumerator.to_a
|
39
|
-
end
|
40
|
-
|
41
|
-
def shift
|
42
|
-
if @buffer.empty?
|
43
|
-
(self.next if next?)
|
44
|
-
else
|
45
|
-
@buffer.shift
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def unshift(*token)
|
50
|
-
@buffer.unshift(*token)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class TokenBuffer < Array
|
55
|
-
attr_accessor :map
|
8
|
+
require "tdparser/token_generator"
|
9
|
+
require "tdparser/token_buffer"
|
10
|
+
require "tdparser/buffer_utils"
|
11
|
+
require "tdparser/parser"
|
12
|
+
require "tdparser/sequence"
|
13
|
+
require "tdparser/non_terminal_parser"
|
14
|
+
require "tdparser/terminal_parser"
|
15
|
+
require "tdparser/composite_parser"
|
16
|
+
require "tdparser/action_parser"
|
17
|
+
require "tdparser/label_parser"
|
18
|
+
require "tdparser/stack_parser"
|
19
|
+
require "tdparser/concat_parser"
|
20
|
+
require "tdparser/choice_parser"
|
21
|
+
require "tdparser/parallel_parser"
|
22
|
+
require "tdparser/iteration_parser"
|
23
|
+
require "tdparser/negative_parser"
|
24
|
+
require "tdparser/fail_parser"
|
25
|
+
require "tdparser/empty_parser"
|
26
|
+
require "tdparser/any_parser"
|
27
|
+
require "tdparser/none_parser"
|
28
|
+
require "tdparser/reference_parser"
|
29
|
+
require "tdparser/backref_parser"
|
30
|
+
require "tdparser/stackref_parser"
|
31
|
+
require "tdparser/condition_parser"
|
32
|
+
require "tdparser/state_parser"
|
33
|
+
require "tdparser/grammar"
|
56
34
|
|
57
|
-
|
58
|
-
|
59
|
-
@map = {}
|
60
|
-
end
|
61
|
-
|
62
|
-
def [](idx)
|
63
|
-
case idx
|
64
|
-
when Symbol, String
|
65
|
-
@map[idx]
|
66
|
-
else
|
67
|
-
super(idx)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def []=(idx, val)
|
72
|
-
case idx
|
73
|
-
when Symbol, String
|
74
|
-
@map[idx] = val
|
75
|
-
else
|
76
|
-
super(idx, val)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def state
|
81
|
-
@map[:__state__]
|
82
|
-
end
|
83
|
-
|
84
|
-
def state=(s)
|
85
|
-
@map[:__state__] = s
|
86
|
-
end
|
87
|
-
|
88
|
-
def clear
|
89
|
-
super()
|
90
|
-
@map.clear
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
class Sequence < Array
|
95
|
-
def +(other)
|
96
|
-
dup.concat(other)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
module BufferUtils
|
101
|
-
def prepare(buff)
|
102
|
-
b = TokenBuffer.new
|
103
|
-
b.map = buff.map
|
104
|
-
b
|
105
|
-
end
|
35
|
+
module TDParser
|
36
|
+
ParserException = Class.new(RuntimeError) # :nodoc: Unused class
|
106
37
|
|
107
|
-
def recover(buff, ts)
|
108
|
-
buff.each { |b| ts.unshift(b) }
|
109
|
-
end
|
110
|
-
end
|
111
38
|
include BufferUtils
|
112
39
|
|
113
|
-
class Parser
|
114
|
-
include BufferUtils
|
115
|
-
include TDParser
|
116
|
-
|
117
|
-
def to_proc
|
118
|
-
proc { |*x| call(*x) }
|
119
|
-
end
|
120
|
-
|
121
|
-
def to_s
|
122
|
-
'??'
|
123
|
-
end
|
124
|
-
|
125
|
-
def call(*args); end
|
126
|
-
|
127
|
-
# def [](*args)
|
128
|
-
# call(*args)
|
129
|
-
# end
|
130
|
-
|
131
|
-
def optimize(_default = false)
|
132
|
-
dup
|
133
|
-
end
|
134
|
-
|
135
|
-
def ==(_other)
|
136
|
-
false
|
137
|
-
end
|
138
|
-
|
139
|
-
def same?(r)
|
140
|
-
self == r
|
141
|
-
end
|
142
|
-
|
143
|
-
def -(other)
|
144
|
-
ConcatParser.new(self, other)
|
145
|
-
end
|
146
|
-
|
147
|
-
def +(other)
|
148
|
-
ParallelParser.new(self, other)
|
149
|
-
end
|
150
|
-
|
151
|
-
def |(other)
|
152
|
-
ChoiceParser.new(self, other).optimize(true)
|
153
|
-
end
|
154
|
-
|
155
|
-
def *(other)
|
156
|
-
if other.is_a?(Range)
|
157
|
-
n = other.min
|
158
|
-
else
|
159
|
-
n = other
|
160
|
-
other = nil
|
161
|
-
end
|
162
|
-
IterationParser.new(self, n, other)
|
163
|
-
end
|
164
|
-
|
165
|
-
def >>(other)
|
166
|
-
ActionParser.new(self, other)
|
167
|
-
end
|
168
|
-
|
169
|
-
def /(other)
|
170
|
-
LabelParser.new(self, other)
|
171
|
-
end
|
172
|
-
|
173
|
-
def %(other)
|
174
|
-
StackParser.new(self, other)
|
175
|
-
end
|
176
|
-
|
177
|
-
def >(other)
|
178
|
-
Parser.new do |tokens, buff|
|
179
|
-
buff[other] = buff.dup
|
180
|
-
self[tokens, buff]
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def ~@
|
185
|
-
NegativeParser.new(self)
|
186
|
-
end
|
187
|
-
|
188
|
-
def parse(tokens = nil, buff = nil, &blk)
|
189
|
-
buff ||= TokenBuffer.new
|
190
|
-
@tokens = if blk.nil?
|
191
|
-
if tokens.respond_to?(:shift) && tokens.respond_to?(:unshift)
|
192
|
-
tokens
|
193
|
-
elsif tokens.respond_to?(:each)
|
194
|
-
TokenGenerator.new(tokens)
|
195
|
-
else
|
196
|
-
tokens
|
197
|
-
end
|
198
|
-
else
|
199
|
-
TokenGenerator.new(&blk)
|
200
|
-
end
|
201
|
-
r = call(@tokens, buff)
|
202
|
-
if r.nil?
|
203
|
-
nil
|
204
|
-
else
|
205
|
-
r[0]
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def peek
|
210
|
-
t = @tokens.shift
|
211
|
-
@tokens.unshift(t) unless t.nil?
|
212
|
-
t
|
213
|
-
end
|
214
|
-
|
215
|
-
def do(&block)
|
216
|
-
self >> block
|
217
|
-
end
|
218
|
-
end
|
219
|
-
# end of Parser
|
220
|
-
|
221
|
-
class NonTerminalParser < Parser
|
222
|
-
attr_reader :context, :symbol, :options
|
223
|
-
|
224
|
-
def initialize(context, sym, *options)
|
225
|
-
@context = context
|
226
|
-
@symbol = sym
|
227
|
-
@options = options
|
228
|
-
end
|
229
|
-
|
230
|
-
def call(tokens, buff)
|
231
|
-
res = nil
|
232
|
-
case @symbol
|
233
|
-
when Symbol, String
|
234
|
-
res = @context.__send__(@symbol, *@options).call(tokens, buff)
|
235
|
-
when Parser
|
236
|
-
res = @symbol.call(tokens, buff)
|
237
|
-
end
|
238
|
-
res
|
239
|
-
end
|
240
|
-
|
241
|
-
def ==(other)
|
242
|
-
(self.class == other.class) &&
|
243
|
-
(@context == other.context) &&
|
244
|
-
(@symbol == other.symbol) &&
|
245
|
-
(@options == other.options)
|
246
|
-
end
|
247
|
-
|
248
|
-
def to_s
|
249
|
-
@symbol.to_s
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
class TerminalParser < Parser
|
254
|
-
attr_reader :symbol, :equality
|
255
|
-
|
256
|
-
def initialize(obj, eqsym)
|
257
|
-
@symbol = obj
|
258
|
-
@equality = eqsym
|
259
|
-
end
|
260
|
-
|
261
|
-
def call(tokens, buff)
|
262
|
-
t = tokens.shift
|
263
|
-
buff.unshift(t)
|
264
|
-
return unless @symbol.__send__(@equality, t) || t.__send__(@equality, @symbol)
|
265
|
-
|
266
|
-
Sequence[t]
|
267
|
-
end
|
268
|
-
|
269
|
-
def ==(other)
|
270
|
-
(self.class == other.class) &&
|
271
|
-
(@symbol == other.symbol) &&
|
272
|
-
(@equality == other.equality)
|
273
|
-
end
|
274
|
-
|
275
|
-
def to_s
|
276
|
-
@symbol.to_s
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
class CompositeParser < Parser
|
281
|
-
attr_accessor :parsers
|
282
|
-
|
283
|
-
def initialize(*parsers)
|
284
|
-
@parsers = parsers
|
285
|
-
end
|
286
|
-
|
287
|
-
def optimize(default = false)
|
288
|
-
parser = dup
|
289
|
-
parser.parsers = @parsers.collect { |x| x.optimize(default) }
|
290
|
-
parser
|
291
|
-
end
|
292
|
-
|
293
|
-
def ==(other)
|
294
|
-
(self.class == other.class) &&
|
295
|
-
(@parsers == other.parsers)
|
296
|
-
end
|
297
|
-
|
298
|
-
def same?(r)
|
299
|
-
super(r) &&
|
300
|
-
@parsers.zip(r.parsers).all? { |x, y| x.same?(y) }
|
301
|
-
end
|
302
|
-
|
303
|
-
def to_s
|
304
|
-
"<composite: #{@parsers.collect(&:to_s)}>"
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
class ActionParser < CompositeParser
|
309
|
-
attr_reader :action
|
310
|
-
|
311
|
-
def initialize(parser, act)
|
312
|
-
@action = act
|
313
|
-
super(parser)
|
314
|
-
end
|
315
|
-
|
316
|
-
def call(tokens, buff)
|
317
|
-
if (x = @parsers[0].call(tokens, buff)).nil?
|
318
|
-
nil
|
319
|
-
else
|
320
|
-
x = TokenBuffer[*x]
|
321
|
-
x.map = buff.map
|
322
|
-
Sequence[@action[x]]
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
def ==(other)
|
327
|
-
super(other) &&
|
328
|
-
(@action == other.action)
|
329
|
-
end
|
330
|
-
|
331
|
-
def to_s
|
332
|
-
"(#{@parsers[0]} <action>)"
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
class LabelParser < CompositeParser
|
337
|
-
attr_reader :label
|
338
|
-
|
339
|
-
def initialize(parser, label)
|
340
|
-
@label = label
|
341
|
-
super(parser)
|
342
|
-
end
|
343
|
-
|
344
|
-
def call(tokens, buff)
|
345
|
-
x = @parsers[0].call(tokens, buff)
|
346
|
-
buff.map[@label] = x
|
347
|
-
x
|
348
|
-
end
|
349
|
-
|
350
|
-
def ==(other)
|
351
|
-
super(other) &&
|
352
|
-
(@label == other.label)
|
353
|
-
end
|
354
|
-
|
355
|
-
def to_s
|
356
|
-
"(#{@parsers[0]}/#{@label})"
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
class StackParser < CompositeParser
|
361
|
-
attr_reader :stack
|
362
|
-
|
363
|
-
def initialize(parser, stack)
|
364
|
-
@stack = stack
|
365
|
-
super(parser)
|
366
|
-
end
|
367
|
-
|
368
|
-
def call(tokens, buff)
|
369
|
-
x = @parsers[0].call(tokens, buff)
|
370
|
-
@stack.push(x)
|
371
|
-
x
|
372
|
-
end
|
373
|
-
|
374
|
-
def ==(other)
|
375
|
-
super(other) &&
|
376
|
-
(@stack == other.stack)
|
377
|
-
end
|
378
|
-
|
379
|
-
def same?(_r)
|
380
|
-
false
|
381
|
-
end
|
382
|
-
|
383
|
-
def to_s
|
384
|
-
"<stack:#{@stack.object_id}>"
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
class ConcatParser < CompositeParser
|
389
|
-
def call(tokens, buff)
|
390
|
-
if (x = @parsers[0].call(tokens, buff)).nil?
|
391
|
-
nil
|
392
|
-
elsif (y = @parsers[1].call(tokens, buff)).nil?
|
393
|
-
nil
|
394
|
-
else
|
395
|
-
x + y
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def -(other)
|
400
|
-
@parsers[0] - (@parsers[1] - other)
|
401
|
-
end
|
402
|
-
|
403
|
-
def to_s
|
404
|
-
"(#{@parsers[0]} #{@parsers[1]})"
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
class ChoiceParser < CompositeParser
|
409
|
-
def call(tokens, buff)
|
410
|
-
b = prepare(buff)
|
411
|
-
if (x = @parsers[0].call(tokens, b)).nil?
|
412
|
-
recover(b, tokens)
|
413
|
-
@parsers[1].call(tokens, buff)
|
414
|
-
else
|
415
|
-
buff.insert(0, *b)
|
416
|
-
x
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
def to_s
|
421
|
-
"(#{@parsers[0]} | #{@parsers[1]})"
|
422
|
-
end
|
423
|
-
|
424
|
-
def shared_sequence(r1, r2)
|
425
|
-
if r1.is_a?(ConcatParser) && r2.is_a?(ConcatParser)
|
426
|
-
r11 = r1.parsers[0]
|
427
|
-
r12 = r1.parsers[1]
|
428
|
-
r21 = r2.parsers[0]
|
429
|
-
r22 = r2.parsers[1]
|
430
|
-
if r11.same?(r21)
|
431
|
-
share, r12, r22, = shared_sequence(r12, r22)
|
432
|
-
return [r11 - share, r12, r22] if share
|
433
|
-
|
434
|
-
return [r11, r12, r22]
|
435
|
-
|
436
|
-
end
|
437
|
-
end
|
438
|
-
[nil, r1, r2]
|
439
|
-
end
|
440
|
-
|
441
|
-
def optimize(default = false)
|
442
|
-
r1 = @parsers[0]
|
443
|
-
r2 = @parsers[1]
|
444
|
-
if r1.is_a?(ActionParser)
|
445
|
-
act1 = r1.action
|
446
|
-
r1 = r1.parsers[0]
|
447
|
-
end
|
448
|
-
if r2.is_a?(ActionParser)
|
449
|
-
act2 = r2.action
|
450
|
-
r2 = r2.parsers[0]
|
451
|
-
end
|
452
|
-
share, r12, r22, = shared_sequence(r1, r2)
|
453
|
-
if share
|
454
|
-
r = share - (r12 + r22)
|
455
|
-
if act1
|
456
|
-
r = if act2
|
457
|
-
r >> proc do |x|
|
458
|
-
y0, y1, *_ = x.pop
|
459
|
-
if y0
|
460
|
-
act1.call(x.push(*y0))
|
461
|
-
else
|
462
|
-
act2.call(x.push(*y1))
|
463
|
-
end
|
464
|
-
end
|
465
|
-
else
|
466
|
-
r >> proc do |x|
|
467
|
-
y0, = x.pop
|
468
|
-
act1.call(x.push(*y0)) if y0
|
469
|
-
end
|
470
|
-
end
|
471
|
-
elsif act2
|
472
|
-
r = r >> proc do |x|
|
473
|
-
_, y1, = x.pop
|
474
|
-
act2.call(x.push(*y1)) if y1
|
475
|
-
end
|
476
|
-
end
|
477
|
-
return r
|
478
|
-
end
|
479
|
-
if default
|
480
|
-
dup
|
481
|
-
else
|
482
|
-
super(default)
|
483
|
-
end
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
class ParallelParser < CompositeParser
|
488
|
-
def call(tokens, buff)
|
489
|
-
b = prepare(buff)
|
490
|
-
if (x = @parsers[0].call(tokens, b)).nil?
|
491
|
-
recover(b, tokens)
|
492
|
-
Sequence[Sequence[nil, @parsers[1].call(tokens, buff)]]
|
493
|
-
else
|
494
|
-
buff.insert(0, *b)
|
495
|
-
Sequence[Sequence[x, nil]]
|
496
|
-
end
|
497
|
-
end
|
498
|
-
|
499
|
-
def to_s
|
500
|
-
"(#{@parsers[0]} + #{@parsers[1]})"
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
class IterationParser < CompositeParser
|
505
|
-
attr_reader :min, :range
|
506
|
-
|
507
|
-
def initialize(parser, n, range)
|
508
|
-
@min = n
|
509
|
-
@range = range
|
510
|
-
super(parser)
|
511
|
-
end
|
512
|
-
|
513
|
-
def call(ts, buff)
|
514
|
-
r = @parsers[0]
|
515
|
-
n = @min
|
516
|
-
x = true
|
517
|
-
xs = []
|
518
|
-
while n.positive?
|
519
|
-
n -= 1
|
520
|
-
b = prepare(buff)
|
521
|
-
if (x = r.call(ts, b)).nil?
|
522
|
-
recover(b, ts)
|
523
|
-
break
|
524
|
-
else
|
525
|
-
buff.insert(0, *b)
|
526
|
-
xs.push(x)
|
527
|
-
end
|
528
|
-
end
|
529
|
-
if x.nil?
|
530
|
-
nil
|
531
|
-
else
|
532
|
-
if range
|
533
|
-
range.each do
|
534
|
-
loop do
|
535
|
-
y = x
|
536
|
-
b = prepare(buff)
|
537
|
-
if (x = r.call(ts, b)).nil?
|
538
|
-
recover(b, ts)
|
539
|
-
x = y
|
540
|
-
break
|
541
|
-
else
|
542
|
-
buff.insert(0, *b)
|
543
|
-
xs.push(x)
|
544
|
-
end
|
545
|
-
end
|
546
|
-
end
|
547
|
-
else
|
548
|
-
loop do
|
549
|
-
y = x
|
550
|
-
b = prepare(buff)
|
551
|
-
if (x = r.call(ts, b)).nil?
|
552
|
-
recover(b, ts)
|
553
|
-
x = y
|
554
|
-
break
|
555
|
-
else
|
556
|
-
buff.insert(0, *b)
|
557
|
-
xs.push(x)
|
558
|
-
end
|
559
|
-
end
|
560
|
-
end
|
561
|
-
Sequence[xs]
|
562
|
-
end
|
563
|
-
end
|
564
|
-
|
565
|
-
def to_s
|
566
|
-
"(#{@parsers[0]})*#{@range ? @range.to_s : @min.to_s}"
|
567
|
-
end
|
568
|
-
|
569
|
-
def ==(other)
|
570
|
-
super(other) &&
|
571
|
-
(@min == other.min) &&
|
572
|
-
(@range == other.range)
|
573
|
-
end
|
574
|
-
end
|
575
|
-
|
576
|
-
class NegativeParser < CompositeParser
|
577
|
-
def call(tokens, buff)
|
578
|
-
b = prepare(buff)
|
579
|
-
r = @parsers[0].call(tokens, b)
|
580
|
-
rev = b.reverse
|
581
|
-
recover(b, tokens)
|
582
|
-
return unless r.nil?
|
583
|
-
|
584
|
-
Sequence[Sequence[*rev]]
|
585
|
-
end
|
586
|
-
|
587
|
-
def to_s
|
588
|
-
"~#{@parsers[0]}"
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
class FailParser < Parser
|
593
|
-
def call(_tokens, _buff)
|
594
|
-
nil
|
595
|
-
end
|
596
|
-
|
597
|
-
def to_s
|
598
|
-
'<fail>'
|
599
|
-
end
|
600
|
-
|
601
|
-
def ==
|
602
|
-
(self.class == r.class)
|
603
|
-
end
|
604
|
-
end
|
605
|
-
|
606
|
-
class EmptyParser < Parser
|
607
|
-
def call(_tokens, _buff)
|
608
|
-
Sequence[nil]
|
609
|
-
end
|
610
|
-
|
611
|
-
def to_s
|
612
|
-
'<empty>'
|
613
|
-
end
|
614
|
-
|
615
|
-
def ==(_other)
|
616
|
-
true
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
|
-
class AnyParser < Parser
|
621
|
-
def call(tokens, _buff)
|
622
|
-
t = tokens.shift
|
623
|
-
if t.nil?
|
624
|
-
nil
|
625
|
-
else
|
626
|
-
Sequence[t]
|
627
|
-
end
|
628
|
-
end
|
629
|
-
|
630
|
-
def to_s
|
631
|
-
'<any>'
|
632
|
-
end
|
633
|
-
|
634
|
-
def ==(_other)
|
635
|
-
true
|
636
|
-
end
|
637
|
-
end
|
638
|
-
|
639
|
-
class NoneParser < Parser
|
640
|
-
def call(tokens, _buff)
|
641
|
-
t = tokens.shift
|
642
|
-
return unless t.nil?
|
643
|
-
|
644
|
-
Sequence[nil]
|
645
|
-
end
|
646
|
-
|
647
|
-
def to_s
|
648
|
-
'<none>'
|
649
|
-
end
|
650
|
-
|
651
|
-
def ==(_other)
|
652
|
-
true
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
class ReferenceParser < Parser
|
657
|
-
def __backref__(xs, eqsym)
|
658
|
-
x = xs.shift
|
659
|
-
xs.inject(token(x, eqsym)) do |acc, x|
|
660
|
-
case x
|
661
|
-
when Sequence
|
662
|
-
acc - __backref__(x, eqsym)
|
663
|
-
else
|
664
|
-
acc - token(x, eqsym)
|
665
|
-
end
|
666
|
-
end
|
667
|
-
end
|
668
|
-
|
669
|
-
def same?(_r)
|
670
|
-
false
|
671
|
-
end
|
672
|
-
end
|
673
|
-
|
674
|
-
class BackrefParser < ReferenceParser
|
675
|
-
attr_reader :label, :equality
|
676
|
-
|
677
|
-
def initialize(label, eqsym)
|
678
|
-
@label = label
|
679
|
-
@equality = eqsym
|
680
|
-
end
|
681
|
-
|
682
|
-
def call(tokens, buff)
|
683
|
-
ys = buff.map[@label]
|
684
|
-
if ys.nil? || ys.empty?
|
685
|
-
nil
|
686
|
-
else
|
687
|
-
__backref__(ys.dup, @equality).call(tokens, buff)
|
688
|
-
end
|
689
|
-
end
|
690
|
-
|
691
|
-
def to_s
|
692
|
-
"<backref:#{@label}>"
|
693
|
-
end
|
694
|
-
|
695
|
-
def ==(other)
|
696
|
-
super(other) &&
|
697
|
-
(@label == other.label) &&
|
698
|
-
(@equality == other.equality)
|
699
|
-
end
|
700
|
-
end
|
701
|
-
|
702
|
-
class StackrefParser < ReferenceParser
|
703
|
-
attr_reader :stack, :equality
|
704
|
-
|
705
|
-
def initialize(stack, eqsym)
|
706
|
-
@stack = stack
|
707
|
-
@equality = eqsym
|
708
|
-
end
|
709
|
-
|
710
|
-
def call(tokens, buff)
|
711
|
-
ys = @stack.pop
|
712
|
-
if ys.nil? || ys.empty?
|
713
|
-
nil
|
714
|
-
else
|
715
|
-
__backref__(ys.dup, @equality).call(tokens, buff)
|
716
|
-
end
|
717
|
-
end
|
718
|
-
|
719
|
-
def to_s
|
720
|
-
"<stackref:#{@stack.object_id}>"
|
721
|
-
end
|
722
|
-
|
723
|
-
def ==(other)
|
724
|
-
super(other) &&
|
725
|
-
@stack.equal?(other.stack) &&
|
726
|
-
(@equality == other.equality)
|
727
|
-
end
|
728
|
-
end
|
729
|
-
|
730
|
-
class ConditionParser < Parser
|
731
|
-
attr_reader :condition
|
732
|
-
|
733
|
-
def initialize(&condition)
|
734
|
-
@condition = condition
|
735
|
-
end
|
736
|
-
|
737
|
-
def call(_tokens, buff)
|
738
|
-
return unless (res = @condition.call(buff.map))
|
739
|
-
|
740
|
-
Sequence[res]
|
741
|
-
end
|
742
|
-
|
743
|
-
def to_s
|
744
|
-
"<condition:#{@condition}>"
|
745
|
-
end
|
746
|
-
|
747
|
-
def ==(other)
|
748
|
-
super(other) &&
|
749
|
-
(@condition == other.condition)
|
750
|
-
end
|
751
|
-
|
752
|
-
def same?(_r)
|
753
|
-
false
|
754
|
-
end
|
755
|
-
end
|
756
|
-
|
757
|
-
class StateParser < Parser
|
758
|
-
attr_reader :state
|
759
|
-
|
760
|
-
def initialize(s)
|
761
|
-
@state = s
|
762
|
-
end
|
763
|
-
|
764
|
-
def call(_tokens, buff)
|
765
|
-
return unless buff.map[:state] == @state
|
766
|
-
|
767
|
-
Sequence[@state]
|
768
|
-
end
|
769
|
-
|
770
|
-
def to_s
|
771
|
-
"<state:#{@state}>"
|
772
|
-
end
|
773
|
-
|
774
|
-
def ==(other)
|
775
|
-
super(other) &&
|
776
|
-
(@state == other.state)
|
777
|
-
end
|
778
|
-
|
779
|
-
def same?(_r)
|
780
|
-
false
|
781
|
-
end
|
782
|
-
end
|
783
|
-
|
784
40
|
def rule(sym, *opts)
|
785
41
|
NonTerminalParser.new(self, sym, *opts)
|
786
42
|
end
|
@@ -789,14 +45,18 @@ module TDParser
|
|
789
45
|
TerminalParser.new(x, eqsym)
|
790
46
|
end
|
791
47
|
|
792
|
-
def
|
48
|
+
def back_ref(x, eqsym = :===)
|
793
49
|
BackrefParser.new(x, eqsym)
|
794
50
|
end
|
795
51
|
|
796
|
-
|
52
|
+
alias backref back_ref
|
53
|
+
|
54
|
+
def stack_ref(stack, eqsym = :===)
|
797
55
|
StackrefParser.new(stack, eqsym)
|
798
56
|
end
|
799
57
|
|
58
|
+
alias stackref stack_ref
|
59
|
+
|
800
60
|
def state(s)
|
801
61
|
StateParser.new(s)
|
802
62
|
end
|
@@ -826,7 +86,7 @@ module TDParser
|
|
826
86
|
end
|
827
87
|
alias condition condition_rule
|
828
88
|
|
829
|
-
def
|
89
|
+
def left_rec(*rules, &act)
|
830
90
|
f = proc do |x|
|
831
91
|
x[1].inject(x[0]) do |acc, y|
|
832
92
|
act.call(Sequence[acc, *y])
|
@@ -836,7 +96,9 @@ module TDParser
|
|
836
96
|
rules.collect { |r| (base - (r * 0)) >> f }.inject(fail) { |acc, r| r | acc }
|
837
97
|
end
|
838
98
|
|
839
|
-
|
99
|
+
alias leftrec left_rec
|
100
|
+
|
101
|
+
def right_rec(*rules, &act)
|
840
102
|
f = proc do |x|
|
841
103
|
x[0].reverse.inject(x[1]) do |acc, y|
|
842
104
|
ys = y.dup
|
@@ -848,39 +110,23 @@ module TDParser
|
|
848
110
|
rules.collect { |r| ((r * 0) - base) >> f }.inject(fail) { |acc, r| r | acc }
|
849
111
|
end
|
850
112
|
|
851
|
-
|
113
|
+
alias rightrec right_rec
|
114
|
+
|
115
|
+
def chain_left(base, *infixes, &)
|
852
116
|
infixes.inject(base) do |acc, r|
|
853
117
|
leftrec(acc, r - acc, &)
|
854
118
|
end
|
855
119
|
end
|
856
120
|
|
857
|
-
|
121
|
+
alias chainl chain_left
|
122
|
+
|
123
|
+
def chain_right(base, *infixes, &)
|
858
124
|
infixes.inject(base) do |acc, r|
|
859
125
|
rightrec(acc - r, acc, &)
|
860
126
|
end
|
861
127
|
end
|
862
128
|
|
863
|
-
|
864
|
-
include TDParser
|
865
|
-
|
866
|
-
alias define instance_eval
|
867
|
-
|
868
|
-
def method_missing(sym, *args)
|
869
|
-
if sym[-1, 1] == '='
|
870
|
-
parser, = args
|
871
|
-
name = sym[0..-2]
|
872
|
-
parser.is_a?(Parser) or parser = token(parser)
|
873
|
-
self.class.instance_eval do
|
874
|
-
instance_methods.include?(name.intern) or
|
875
|
-
define_method(name) { parser }
|
876
|
-
end
|
877
|
-
elsif args.empty?
|
878
|
-
rule(sym)
|
879
|
-
else
|
880
|
-
raise(NoMethodError, "undefined method `#{sym}' for #{inspect}")
|
881
|
-
end
|
882
|
-
end
|
883
|
-
end
|
129
|
+
alias chainr chain_right
|
884
130
|
|
885
131
|
def self.define(*_args, &)
|
886
132
|
klass = Class.new(Grammar)
|