rley 0.8.00 → 0.8.05
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +47 -3
- data/CHANGELOG.md +32 -4
- data/examples/NLP/pico_en_demo.rb +2 -2
- data/examples/data_formats/JSON/README.md +34 -0
- data/examples/data_formats/JSON/sample01.json +3 -0
- data/examples/data_formats/JSON/sample01.svg +36 -0
- data/examples/data_formats/JSON/sample02.json +6 -0
- data/examples/data_formats/JSON/sample02.svg +128 -0
- data/examples/data_formats/JSON/sample03.json +88 -0
- data/examples/general/calc_iter1/README.md +26 -0
- data/examples/general/calc_iter2/README.md +55 -0
- data/examples/general/general_examples.md +37 -0
- data/examples/tokenizer/README.md +46 -0
- data/examples/tokenizer/loxxy_raw_scanner.rex +98 -0
- data/examples/tokenizer/loxxy_raw_scanner.rex.rb +256 -0
- data/examples/tokenizer/loxxy_tokenizer.rb +94 -0
- data/examples/tokenizer/run_tokenizer.rb +29 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/lexical/literal.rb +29 -0
- data/lib/rley/lexical/token.rb +7 -4
- data/lib/rley/notation/all_notation_nodes.rb +3 -1
- data/lib/rley/notation/ast_builder.rb +185 -191
- data/lib/rley/notation/ast_node.rb +5 -5
- data/lib/rley/notation/ast_visitor.rb +3 -1
- data/lib/rley/notation/grammar.rb +1 -1
- data/lib/rley/notation/grammar_builder.rb +87 -33
- data/lib/rley/notation/grouping_node.rb +1 -1
- data/lib/rley/notation/parser.rb +56 -56
- data/lib/rley/notation/sequence_node.rb +3 -3
- data/lib/rley/notation/symbol_node.rb +2 -2
- data/lib/rley/notation/tokenizer.rb +3 -15
- data/lib/rley/parse_rep/ast_base_builder.rb +35 -4
- data/lib/rley/parser/gfg_chart.rb +5 -4
- data/lib/rley/parser/gfg_earley_parser.rb +1 -1
- data/lib/rley/syntax/base_grammar_builder.rb +8 -2
- data/lib/rley/syntax/match_closest.rb +7 -7
- data/lib/rley.rb +1 -1
- data/spec/rley/lexical/literal_spec.rb +33 -0
- data/spec/rley/lexical/token_spec.rb +15 -4
- data/spec/rley/notation/grammar_builder_spec.rb +57 -50
- data/spec/rley/notation/parser_spec.rb +183 -184
- data/spec/rley/notation/tokenizer_spec.rb +98 -104
- data/spec/rley/parser/dangling_else_spec.rb +20 -20
- data/spec/rley/parser/gfg_chart_spec.rb +0 -1
- data/spec/rley/parser/gfg_earley_parser_spec.rb +166 -147
- data/spec/rley/parser/gfg_parsing_spec.rb +2 -2
- data/spec/rley/syntax/base_grammar_builder_spec.rb +7 -8
- data/spec/rley/syntax/grammar_spec.rb +6 -9
- data/spec/rley/syntax/match_closest_spec.rb +4 -4
- metadata +19 -9
- data/lib/rley/parser/parse_tracer.rb +0 -103
- data/lib/rley/syntax/literal.rb +0 -20
- data/lib/rley/syntax/verbatim_symbol.rb +0 -27
- data/spec/rley/syntax/literal_spec.rb +0 -31
- data/spec/rley/syntax/verbatim_symbol_spec.rb +0 -38
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../spec_helper'
|
4
4
|
require 'stringio'
|
5
|
-
require_relative '../../../lib/rley/syntax/
|
5
|
+
require_relative '../../../lib/rley/syntax/terminal'
|
6
6
|
require_relative '../../../lib/rley/syntax/non_terminal'
|
7
7
|
require_relative '../../../lib/rley/syntax/production'
|
8
8
|
require_relative '../../../lib/rley/syntax/base_grammar_builder'
|
@@ -22,6 +22,7 @@ require_relative '../support/expectation_helper'
|
|
22
22
|
require_relative '../../../lib/rley/parser/gfg_earley_parser'
|
23
23
|
|
24
24
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
25
|
+
# rubocop: disable Metrics/BlockLength
|
25
26
|
module Parser # Open this namespace to avoid module qualifier prefixes
|
26
27
|
describe GFGEarleyParser do
|
27
28
|
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
@@ -53,12 +54,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
53
54
|
let(:nt_S) { Syntax::NonTerminal.new('S') }
|
54
55
|
let(:nt_M) { Syntax::NonTerminal.new('M') }
|
55
56
|
let(:nt_T) { Syntax::NonTerminal.new('T') }
|
56
|
-
let(:plus) { Syntax::
|
57
|
-
let(:star) { Syntax::
|
58
|
-
let(:integer)
|
59
|
-
integer_pattern = /[-+]?[0-9]+/ # Decimal notation
|
60
|
-
Syntax::Literal.new('integer', integer_pattern)
|
61
|
-
end
|
57
|
+
let(:plus) { Syntax::Terminal.new('+') }
|
58
|
+
let(:star) { Syntax::Terminal.new('*') }
|
59
|
+
let(:integer) { Syntax::Terminal.new('integer') }
|
62
60
|
let(:prod_P) { Syntax::Production.new(nt_P, [nt_S]) }
|
63
61
|
let(:prod_S1) { Syntax::Production.new(nt_S, [nt_S, plus, nt_M]) }
|
64
62
|
let(:prod_S2) { Syntax::Production.new(nt_S, [nt_M]) }
|
@@ -196,16 +194,16 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
196
194
|
###################### S(0): . 2 + 3 * 4
|
197
195
|
# Expectation chart[0]:
|
198
196
|
expected = [
|
199
|
-
'.P | 0',
|
200
|
-
'P => . S | 0',
|
201
|
-
'.S | 0',
|
202
|
-
|
203
|
-
'S => . M | 0',
|
204
|
-
'.M | 0',
|
205
|
-
|
206
|
-
'M => . T | 0',
|
207
|
-
'.T | 0',
|
208
|
-
'T => . integer | 0'
|
197
|
+
'.P | 0', # Initialization
|
198
|
+
'P => . S | 0', # start rule
|
199
|
+
'.S | 0', # call rule
|
200
|
+
'S => . S + M | 0', # start rule
|
201
|
+
'S => . M | 0', # start rule
|
202
|
+
'.M | 0', # call rule
|
203
|
+
'M => . M * T | 0', # start rule
|
204
|
+
'M => . T | 0', # start rule
|
205
|
+
'.T | 0', # call rule
|
206
|
+
'T => . integer | 0' # start rule
|
209
207
|
]
|
210
208
|
compare_entry_texts(parse_result.chart[0], expected)
|
211
209
|
|
@@ -213,16 +211,16 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
213
211
|
###################### S(1): 2 . + 3 * 4
|
214
212
|
# Expectation chart[1]:
|
215
213
|
expected = [
|
216
|
-
'T => integer . | 0',
|
217
|
-
'T. | 0',
|
218
|
-
'M => T . | 0',
|
219
|
-
'M. | 0',
|
220
|
-
'S => M . | 0',
|
221
|
-
|
222
|
-
'S. | 0',
|
223
|
-
'P => S . | 0',
|
224
|
-
|
225
|
-
'P. | 0'
|
214
|
+
'T => integer . | 0', # scan '2'
|
215
|
+
'T. | 0', # exit rule
|
216
|
+
'M => T . | 0', # end rule
|
217
|
+
'M. | 0', # exit rule
|
218
|
+
'S => M . | 0', # end rule
|
219
|
+
'M => M . * T | 0', # end rule
|
220
|
+
'S. | 0', # exit rule
|
221
|
+
'P => S . | 0', # end rule
|
222
|
+
'S => S . + M | 0', # end rule
|
223
|
+
'P. | 0' # exit rule
|
226
224
|
]
|
227
225
|
compare_entry_texts(parse_result.chart[1], expected)
|
228
226
|
|
@@ -230,12 +228,12 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
230
228
|
###################### S(2): 2 + . 3 * 4
|
231
229
|
# Expectation chart[2]:
|
232
230
|
expected = [
|
233
|
-
|
234
|
-
'.M | 2',
|
235
|
-
|
236
|
-
'M => . T | 2',
|
237
|
-
'.T | 2',
|
238
|
-
'T => . integer | 2'
|
231
|
+
'S => S + . M | 0', # scan '+'
|
232
|
+
'.M | 2', # call rule
|
233
|
+
'M => . M * T | 2', # start rule
|
234
|
+
'M => . T | 2', # start rule
|
235
|
+
'.T | 2', # call rule
|
236
|
+
'T => . integer | 2' # start rule
|
239
237
|
]
|
240
238
|
compare_entry_texts(parse_result.chart[2], expected)
|
241
239
|
|
@@ -243,41 +241,41 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
243
241
|
###################### S(3): 2 + 3 . * 4
|
244
242
|
# Expectation chart[3]:
|
245
243
|
expected = [
|
246
|
-
'T => integer . | 2',
|
247
|
-
'T. | 2',
|
248
|
-
'M => T . | 2',
|
249
|
-
'M. | 2',
|
250
|
-
|
251
|
-
|
252
|
-
'S. | 0',
|
253
|
-
'P => S . | 0',
|
254
|
-
|
255
|
-
'P. | 0'
|
244
|
+
'T => integer . | 2', # scan '3'
|
245
|
+
'T. | 2', # exit rule
|
246
|
+
'M => T . | 2', # end rule
|
247
|
+
'M. | 2', # exit rule
|
248
|
+
'S => S + M . | 0', # end rule
|
249
|
+
'M => M . * T | 2', # end rule
|
250
|
+
'S. | 0', # exit rule
|
251
|
+
'P => S . | 0', # end rule
|
252
|
+
'S => S . + M | 0', # end rule
|
253
|
+
'P. | 0' # exit rule
|
256
254
|
]
|
257
255
|
compare_entry_texts(parse_result.chart[3], expected)
|
258
256
|
|
259
257
|
###################### S(4): 2 + 3 * . 4
|
260
258
|
# Expectation chart[4]:
|
261
259
|
expected = [
|
262
|
-
|
263
|
-
'.T | 4',
|
264
|
-
'T => . integer | 4'
|
260
|
+
'M => M * . T | 2', # scan '*'
|
261
|
+
'.T | 4', # call rule
|
262
|
+
'T => . integer | 4' # entry rule
|
265
263
|
]
|
266
264
|
compare_entry_texts(parse_result.chart[4], expected)
|
267
265
|
|
268
266
|
###################### S(5): 2 + 3 * 4 .
|
269
267
|
# Expectation chart[5]:
|
270
268
|
expected = [
|
271
|
-
'T => integer . | 4',
|
272
|
-
'T. | 4',
|
273
|
-
|
274
|
-
'M. | 2',
|
275
|
-
|
276
|
-
|
277
|
-
'S. | 0',
|
278
|
-
'P => S . | 0',
|
279
|
-
|
280
|
-
'P. | 0'
|
269
|
+
'T => integer . | 4', # scan '4'
|
270
|
+
'T. | 4', # exit rule
|
271
|
+
'M => M * T . | 2', # end rule
|
272
|
+
'M. | 2', # exit rule
|
273
|
+
'S => S + M . | 0', # end rule
|
274
|
+
'M => M . * T | 2', # end rule
|
275
|
+
'S. | 0', # exit rule
|
276
|
+
'P => S . | 0', # end rule
|
277
|
+
'S => S . + M | 0', # end rule
|
278
|
+
'P. | 0' # end rule
|
281
279
|
]
|
282
280
|
compare_entry_texts(parse_result.chart[5], expected)
|
283
281
|
end
|
@@ -302,7 +300,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
302
300
|
'sequence => . sequence comma integer | 0', # start rule
|
303
301
|
'sequence => . integer | 0', # start rule
|
304
302
|
'.integer | 0', # call rule
|
305
|
-
'integer => . digit_plus | 0'
|
303
|
+
'integer => . digit_plus | 0', # start rule
|
306
304
|
'.digit_plus | 0', # call rule
|
307
305
|
'digit_plus => . digit_plus digit | 0', # start rule (generated)
|
308
306
|
'digit_plus => . digit | 0' # start rule (generated)
|
@@ -314,7 +312,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
314
312
|
expected = [
|
315
313
|
'digit_plus => digit . | 0', # Scan
|
316
314
|
'digit_plus. | 0', # exit rule
|
317
|
-
'integer => digit_plus . | 0'
|
315
|
+
'integer => digit_plus . | 0', # end rule
|
318
316
|
'digit_plus => digit_plus . digit | 0', # rule (generated)
|
319
317
|
'integer. | 0', # exit rule
|
320
318
|
'sequence => integer . | 0', # end rule
|
@@ -329,8 +327,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
329
327
|
# Expectation chart[2]:
|
330
328
|
expected = [
|
331
329
|
'sequence => sequence comma . integer | 0', # Scan
|
332
|
-
'.integer | 2',
|
333
|
-
'integer => . digit_plus | 2'
|
330
|
+
'.integer | 2', # call rule
|
331
|
+
'integer => . digit_plus | 2', # start rule
|
334
332
|
'.digit_plus | 2', # call rule
|
335
333
|
'digit_plus => . digit_plus digit | 2', # start rule (generated)
|
336
334
|
'digit_plus => . digit | 2' # start rule (generated)
|
@@ -342,13 +340,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
342
340
|
expected = [
|
343
341
|
'digit_plus => digit . | 2', # Scan
|
344
342
|
'digit_plus. | 2', # exit rule
|
345
|
-
'integer => digit_plus . | 2'
|
343
|
+
'integer => digit_plus . | 2', # end rule
|
346
344
|
'digit_plus => digit_plus . digit | 2', # rule (generated)
|
347
345
|
'integer. | 2', # exit rule
|
348
346
|
'sequence => sequence comma integer . | 0', # rule
|
349
|
-
'sequence. | 0',
|
347
|
+
'sequence. | 0', # exit rule
|
350
348
|
'S => sequence . | 0', # end rule
|
351
|
-
'sequence => sequence . comma integer | 0'
|
349
|
+
'sequence => sequence . comma integer | 0' # rule
|
352
350
|
]
|
353
351
|
compare_entry_texts(parse_result.chart[3], expected)
|
354
352
|
|
@@ -357,12 +355,12 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
357
355
|
expected = [
|
358
356
|
'digit_plus => digit_plus digit . | 2', # Scan
|
359
357
|
'digit_plus. | 2', # exit rule
|
360
|
-
'integer => digit_plus . | 2'
|
358
|
+
'integer => digit_plus . | 2', # end rule
|
361
359
|
'digit_plus => digit_plus . digit | 2', #
|
362
360
|
'integer. | 2', # exit rule
|
363
361
|
'sequence => sequence comma integer . | 0', # rule
|
364
362
|
'sequence. | 0', # exit rule
|
365
|
-
'S => sequence . | 0'
|
363
|
+
'S => sequence . | 0' # end rule
|
366
364
|
]
|
367
365
|
compare_entry_texts(parse_result.chart[4], expected)
|
368
366
|
end
|
@@ -372,7 +370,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
372
370
|
# (based on example in D. Grune, C. Jacobs "Parsing Techniques" book)
|
373
371
|
# Ss => A A 'x';
|
374
372
|
# A => ;
|
375
|
-
t_x = Syntax::
|
373
|
+
t_x = Syntax::Terminal.new('x')
|
376
374
|
|
377
375
|
builder = Notation::GrammarBuilder.new do
|
378
376
|
add_terminals(t_x)
|
@@ -389,21 +387,21 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
389
387
|
###################### S(0): . x
|
390
388
|
# Expectation chart[0]:
|
391
389
|
expected = [
|
392
|
-
'.Ss | 0',
|
393
|
-
|
394
|
-
'.A | 0',
|
395
|
-
'A => . | 0',
|
396
|
-
'A. | 0',
|
397
|
-
|
398
|
-
|
390
|
+
'.Ss | 0', # Initialization
|
391
|
+
'Ss => . A A x | 0', # start rule
|
392
|
+
'.A | 0', # call rule
|
393
|
+
'A => . | 0', # start rule
|
394
|
+
'A. | 0', # exit rule
|
395
|
+
'Ss => A . A x | 0', # end rule
|
396
|
+
'Ss => A A . x | 0' # end rule
|
399
397
|
]
|
400
398
|
compare_entry_texts(parse_result.chart[0], expected)
|
401
399
|
|
402
400
|
###################### S(1): x .
|
403
401
|
# Expectation chart[1]:
|
404
402
|
expected = [
|
405
|
-
|
406
|
-
'Ss. | 0'
|
403
|
+
'Ss => A A x . | 0', # scan 'x'
|
404
|
+
'Ss. | 0' # exit rule
|
407
405
|
]
|
408
406
|
compare_entry_texts(parse_result.chart[1], expected)
|
409
407
|
end
|
@@ -416,9 +414,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
416
414
|
# S => S "*" S.
|
417
415
|
# S => L.
|
418
416
|
# L => an integer number token.
|
419
|
-
t_int = Syntax::
|
420
|
-
t_plus = Syntax::
|
421
|
-
t_star = Syntax::
|
417
|
+
t_int = Syntax::Terminal.new('integer')
|
418
|
+
t_plus = Syntax::Terminal.new('+')
|
419
|
+
t_star = Syntax::Terminal.new('*')
|
422
420
|
|
423
421
|
builder = Syntax::BaseGrammarBuilder.new do
|
424
422
|
add_terminals(t_int, t_plus, t_star)
|
@@ -448,8 +446,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
448
446
|
'.P | 0', # Initialization
|
449
447
|
'P => . S | 0', # start rule
|
450
448
|
'.S | 0', # call rule
|
451
|
-
|
452
|
-
|
449
|
+
'S => . S + S | 0', # entry rule
|
450
|
+
'S => . S * S | 0', # entry rule
|
453
451
|
'S => . L | 0', # entry rule
|
454
452
|
'.L | 0', # call rule
|
455
453
|
'L => . integer | 0' # entry rule
|
@@ -464,8 +462,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
464
462
|
'S => L . | 0', # end rule
|
465
463
|
'S. | 0', # exit rule
|
466
464
|
'P => S . | 0', # end rule
|
467
|
-
|
468
|
-
|
465
|
+
'S => S . + S | 0', # end rule
|
466
|
+
'S => S . * S | 0', # end rule
|
469
467
|
'P. | 0' # exit rule
|
470
468
|
]
|
471
469
|
compare_entry_texts(parse_result.chart[1], expected)
|
@@ -473,10 +471,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
473
471
|
###################### S(2): 2 + . 3 * 4
|
474
472
|
# Expectation chart[2]:
|
475
473
|
expected = [
|
476
|
-
|
474
|
+
'S => S + . S | 0', # scan '+'
|
477
475
|
'.S | 2', # call rule
|
478
|
-
|
479
|
-
|
476
|
+
'S => . S + S | 2', # entry rule
|
477
|
+
'S => . S * S | 2', # entry rule
|
480
478
|
'S => . L | 2', # entry rule
|
481
479
|
'.L | 2', # call rule
|
482
480
|
'L => . integer | 2' # entry rule
|
@@ -490,13 +488,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
490
488
|
'L. | 2', # exit rule
|
491
489
|
'S => L . | 2', # end rule
|
492
490
|
'S. | 2', # exit rule
|
493
|
-
|
494
|
-
|
495
|
-
|
491
|
+
'S => S + S . | 0', # end rule
|
492
|
+
'S => S . + S | 2', # end rule
|
493
|
+
'S => S . * S | 2', # end rule
|
496
494
|
'S. | 0', # exit rule
|
497
495
|
'P => S . | 0', # end rule
|
498
|
-
|
499
|
-
|
496
|
+
'S => S . + S | 0', # end rule
|
497
|
+
'S => S . * S | 0', # end rule
|
500
498
|
'P. | 0' # exit rule
|
501
499
|
]
|
502
500
|
compare_entry_texts(parse_result.chart[3], expected)
|
@@ -504,11 +502,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
504
502
|
###################### S(4): 2 + 3 * . 4
|
505
503
|
# Expectation chart[4]:
|
506
504
|
expected = [
|
507
|
-
|
508
|
-
|
505
|
+
'S => S * . S | 2', # scan '*'
|
506
|
+
'S => S * . S | 0', # scan '*'
|
509
507
|
'.S | 4', # call rule
|
510
|
-
|
511
|
-
|
508
|
+
'S => . S + S | 4', # entry rule
|
509
|
+
'S => . S * S | 4', # entry rule
|
512
510
|
'S => . L | 4', # entry rule
|
513
511
|
'.L | 4', # call rule
|
514
512
|
'L => . integer | 4' # entry rule
|
@@ -522,18 +520,18 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
522
520
|
'L. | 4', # exit rule
|
523
521
|
'S => L . | 4', # end rule
|
524
522
|
'S. | 4', # exit rule
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
523
|
+
'S => S * S . | 2', # end rule
|
524
|
+
'S => S * S . | 0', # end rule
|
525
|
+
'S => S . + S | 4', # end rule
|
526
|
+
'S => S . * S | 4', # end rule
|
529
527
|
'S. | 2', # exit rule
|
530
528
|
'S. | 0', # exit rule
|
531
|
-
|
532
|
-
|
533
|
-
|
529
|
+
'S => S + S . | 0', # end rule
|
530
|
+
'S => S . + S | 2', # end rule
|
531
|
+
'S => S . * S | 2', # end rule
|
534
532
|
'P => S . | 0', # end rule
|
535
|
-
|
536
|
-
|
533
|
+
'S => S . + S | 0', # end rule
|
534
|
+
'S => S . * S | 0', # end rule
|
537
535
|
'P. | 0' # exit rule
|
538
536
|
]
|
539
537
|
compare_entry_texts(parse_result.chart[5], expected)
|
@@ -543,18 +541,18 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
543
541
|
'L. | 4' => ['L => integer . | 4'],
|
544
542
|
'S => L . | 4' => ['L. | 4'],
|
545
543
|
'S. | 4' => ['S => L . | 4'],
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
'S. | 2' => [
|
551
|
-
'S. | 0' => [
|
552
|
-
|
553
|
-
|
554
|
-
|
544
|
+
'S => S * S . | 2' => ['S. | 4'],
|
545
|
+
'S => S * S . | 0' => ['S. | 4'],
|
546
|
+
'S => S . + S | 4' => ['S. | 4'],
|
547
|
+
'S => S . * S | 4' => ['S. | 4'],
|
548
|
+
'S. | 2' => ['S => S * S . | 2'],
|
549
|
+
'S. | 0' => ['S => S * S . | 0', 'S => S + S . | 0'],
|
550
|
+
'S => S + S . | 0' => ['S. | 2'],
|
551
|
+
'S => S . + S | 2' => ['S. | 2'],
|
552
|
+
'S => S . * S | 2' => ['S. | 2'],
|
555
553
|
'P => S . | 0' => ['S. | 0'],
|
556
|
-
|
557
|
-
|
554
|
+
'S => S . + S | 0' => ['S. | 0'],
|
555
|
+
'S => S . * S | 0' => ['S. | 0'],
|
558
556
|
'P. | 0' => ['P => S . | 0']
|
559
557
|
}
|
560
558
|
check_antecedence(parse_result, 5, expected_antecedents)
|
@@ -815,9 +813,9 @@ MSG
|
|
815
813
|
# Q ::= *.
|
816
814
|
# Q ::= /.
|
817
815
|
# Q ::=.
|
818
|
-
t_a = Syntax::
|
819
|
-
t_star = Syntax::
|
820
|
-
t_slash = Syntax::
|
816
|
+
t_a = Syntax::Terminal.new('a')
|
817
|
+
t_star = Syntax::Terminal.new('*')
|
818
|
+
t_slash = Syntax::Terminal.new('/')
|
821
819
|
|
822
820
|
builder = Syntax::BaseGrammarBuilder.new do
|
823
821
|
add_terminals(t_a, t_star, t_slash)
|
@@ -845,35 +843,35 @@ MSG
|
|
845
843
|
'E => . E Q F | 0', # start rule
|
846
844
|
'E => . F | 0', # start rule
|
847
845
|
'.F | 0', # call rule
|
848
|
-
|
846
|
+
'F => . a | 0' # start rule
|
849
847
|
]
|
850
848
|
compare_entry_texts(parse_result.chart[0], expected)
|
851
849
|
|
852
850
|
###################### S(1) == a . a / a
|
853
851
|
# Expectation chart[1]:
|
854
852
|
expected = [
|
855
|
-
|
856
|
-
'F. | 0',
|
857
|
-
'E => F . | 0',
|
858
|
-
'E. | 0',
|
859
|
-
'Z => E . | 0',
|
860
|
-
'E => E . Q F | 0',
|
861
|
-
'Z. | 0',
|
862
|
-
'.Q | 1',
|
863
|
-
|
864
|
-
|
865
|
-
'Q => . | 1',
|
866
|
-
'Q. | 1',
|
867
|
-
'E => E Q . F | 0',
|
868
|
-
'.F | 1',
|
869
|
-
|
853
|
+
'F => a . | 0', # scan 'a'
|
854
|
+
'F. | 0', # exit rule
|
855
|
+
'E => F . | 0', # end rule
|
856
|
+
'E. | 0', # exit rule
|
857
|
+
'Z => E . | 0', # end rule
|
858
|
+
'E => E . Q F | 0', # end rule
|
859
|
+
'Z. | 0', # exit rule
|
860
|
+
'.Q | 1', # call rule
|
861
|
+
'Q => . * | 1', # start rule
|
862
|
+
'Q => . / | 1', # start rule
|
863
|
+
'Q => . | 1', # start rule
|
864
|
+
'Q. | 1', # exit rule
|
865
|
+
'E => E Q . F | 0', # end rule
|
866
|
+
'.F | 1', # call rule
|
867
|
+
'F => . a | 1' # start rule
|
870
868
|
]
|
871
869
|
compare_entry_texts(parse_result.chart[1], expected)
|
872
870
|
|
873
871
|
###################### S(2) == a a . / a
|
874
872
|
# Expectation chart[2]:
|
875
873
|
expected = [
|
876
|
-
|
874
|
+
'F => a . | 1', # scan 'a'
|
877
875
|
'F. | 1', # exit rule
|
878
876
|
'E => E Q F . | 0', # end rule
|
879
877
|
'E. | 0', # exit rule
|
@@ -881,13 +879,13 @@ MSG
|
|
881
879
|
'E => E . Q F | 0', # end rule
|
882
880
|
'Z. | 0', # exit rule
|
883
881
|
'.Q | 2', # call rule
|
884
|
-
|
885
|
-
|
882
|
+
'Q => . * | 2', # start rule
|
883
|
+
'Q => . / | 2', # start rule
|
886
884
|
'Q => . | 2', # start rule
|
887
885
|
'Q. | 2', # exit rule
|
888
886
|
'E => E Q . F | 0', # end rule
|
889
887
|
'.F | 2', # call rule
|
890
|
-
|
888
|
+
'F => . a | 2' # start rule
|
891
889
|
]
|
892
890
|
compare_entry_texts(parse_result.chart[2], expected)
|
893
891
|
|
@@ -895,11 +893,11 @@ MSG
|
|
895
893
|
###################### S(3) == a a / . a
|
896
894
|
# Expectation chart[3]:
|
897
895
|
expected = [
|
898
|
-
|
896
|
+
'Q => / . | 2', # scan '/'
|
899
897
|
'Q. | 2', # exit rule
|
900
898
|
'E => E Q . F | 0', # end rule
|
901
899
|
'.F | 3', # call rule
|
902
|
-
|
900
|
+
'F => . a | 3' # entry rule
|
903
901
|
]
|
904
902
|
compare_entry_texts(parse_result.chart[3], expected)
|
905
903
|
|
@@ -907,7 +905,7 @@ MSG
|
|
907
905
|
###################### S(4) == a a / a .
|
908
906
|
# Expectation chart[4]:
|
909
907
|
expected = [
|
910
|
-
|
908
|
+
'F => a . | 3', # scan 'a'
|
911
909
|
'F. | 3', # exit rule
|
912
910
|
'E => E Q F . | 0', # end rule
|
913
911
|
'E. | 0', # exit rule
|
@@ -915,13 +913,13 @@ MSG
|
|
915
913
|
'E => E . Q F | 0', # end rule
|
916
914
|
'Z. | 0', # exit rule
|
917
915
|
'.Q | 4', # call rule
|
918
|
-
|
919
|
-
|
916
|
+
'Q => . * | 4', # start rule
|
917
|
+
'Q => . / | 4', # start rule
|
920
918
|
'Q => . | 4', # start rule
|
921
919
|
'Q. | 4', # exit rule
|
922
920
|
'E => E Q . F | 0', # end rule
|
923
921
|
'.F | 4', # call rule
|
924
|
-
|
922
|
+
'F => . a | 4' # entry rule
|
925
923
|
]
|
926
924
|
compare_entry_texts(parse_result.chart[4], expected)
|
927
925
|
end
|
@@ -934,10 +932,11 @@ MSG
|
|
934
932
|
# S => ;
|
935
933
|
# This grammar requires a time that is quadratic in the number of
|
936
934
|
# input tokens
|
937
|
-
builder = Notation::GrammarBuilder.new
|
938
|
-
|
939
|
-
|
940
|
-
|
935
|
+
builder = Notation::GrammarBuilder.new do
|
936
|
+
add_terminals('a')
|
937
|
+
rule('S' => 'a S')
|
938
|
+
rule('S' => '')
|
939
|
+
end
|
941
940
|
grammar = builder.grammar
|
942
941
|
tokens = build_token_sequence(%w[a a a a], grammar)
|
943
942
|
|
@@ -1017,8 +1016,28 @@ MSG
|
|
1017
1016
|
]
|
1018
1017
|
compare_entry_texts(parse_result.chart[4], expected)
|
1019
1018
|
end
|
1019
|
+
|
1020
|
+
it 'should support modifier(s) in start rule' do
|
1021
|
+
# An implicit EOF marker is a special terminal
|
1022
|
+
# that denotes the end of input string but doesn't
|
1023
|
+
# appear explicitly as some character or text in the input.
|
1024
|
+
builder = Notation::GrammarBuilder.new do
|
1025
|
+
add_terminals('a', 'b', 'EOF')
|
1026
|
+
|
1027
|
+
rule('S' => 'a_or_b* EOF')
|
1028
|
+
rule('a_or_b' => 'a')
|
1029
|
+
rule('a_or_b' => 'b')
|
1030
|
+
end
|
1031
|
+
grammar = builder.grammar
|
1032
|
+
tokens = build_token_sequence(%w[EOF], grammar)
|
1033
|
+
tokens[0].instance_variable_set(:@lexeme, '')
|
1034
|
+
instance = GFGEarleyParser.new(grammar)
|
1035
|
+
parse_result = instance.parse(tokens)
|
1036
|
+
expect(parse_result.success?).to eq(true)
|
1037
|
+
end
|
1020
1038
|
end # context
|
1021
1039
|
end # describe
|
1022
1040
|
end # module
|
1041
|
+
# rubocop: enable Metrics/BlockLength
|
1023
1042
|
end # module
|
1024
1043
|
# End of file
|
@@ -4,12 +4,11 @@ require_relative '../../spec_helper'
|
|
4
4
|
require 'stringio'
|
5
5
|
|
6
6
|
require_relative '../../../lib/rley/syntax/non_terminal'
|
7
|
-
require_relative '../../../lib/rley/syntax/
|
7
|
+
require_relative '../../../lib/rley/syntax/terminal'
|
8
8
|
require_relative '../../../lib/rley/syntax/production'
|
9
9
|
require_relative '../../../lib/rley/syntax/base_grammar_builder'
|
10
10
|
require_relative '../../../lib/rley/base/dotted_item'
|
11
11
|
require_relative '../../../lib/rley/lexical/token'
|
12
|
-
require_relative '../../../lib/rley/parser/parse_tracer'
|
13
12
|
require_relative '../../../lib/rley/gfg/grm_flow_graph'
|
14
13
|
require_relative '../../../lib/rley/base/grm_items_builder'
|
15
14
|
require_relative '../support/grammar_abc_helper'
|
@@ -316,6 +315,7 @@ State[5]
|
|
316
315
|
S => S . + M | 0
|
317
316
|
P. | 0
|
318
317
|
REPR
|
318
|
+
expect(expectation).to eq(expectation)
|
319
319
|
end
|
320
320
|
end # context
|
321
321
|
|
@@ -55,8 +55,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
55
55
|
|
56
56
|
it 'should accept already built terminals' do
|
57
57
|
a = Terminal.new('a')
|
58
|
-
b =
|
59
|
-
c =
|
58
|
+
b = Terminal.new('b')
|
59
|
+
c = Terminal.new('c')
|
60
60
|
|
61
61
|
subject.add_terminals(a, b, c)
|
62
62
|
expect(subject.symbols.size).to eq(3)
|
@@ -67,8 +67,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
67
67
|
|
68
68
|
it 'should accept already built terminals' do
|
69
69
|
a = Terminal.new('a')
|
70
|
-
b =
|
71
|
-
c =
|
70
|
+
b = Terminal.new('b')
|
71
|
+
c = Terminal.new('c')
|
72
72
|
|
73
73
|
subject.add_terminals(a, b, c)
|
74
74
|
expect(subject.symbols.size).to eq(3)
|
@@ -133,7 +133,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
133
133
|
expect(last_prod.lhs.name).to eq('value')
|
134
134
|
expect(last_prod.rhs.members[0].name).to eq('digit_plus')
|
135
135
|
end
|
136
|
-
|
137
136
|
end # context
|
138
137
|
|
139
138
|
context 'Building grammar:' do
|
@@ -198,9 +197,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
198
197
|
# Q ::= *.
|
199
198
|
# Q ::= /.
|
200
199
|
# Q ::=.
|
201
|
-
t_a =
|
202
|
-
t_star =
|
203
|
-
t_slash =
|
200
|
+
t_a = Terminal.new('a')
|
201
|
+
t_star = Terminal.new('*')
|
202
|
+
t_slash = Terminal.new('/')
|
204
203
|
|
205
204
|
builder = BaseGrammarBuilder.new
|
206
205
|
builder.add_terminals(t_a, t_star, t_slash)
|