rley 0.8.00 → 0.8.05

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +47 -3
  3. data/CHANGELOG.md +32 -4
  4. data/examples/NLP/pico_en_demo.rb +2 -2
  5. data/examples/data_formats/JSON/README.md +34 -0
  6. data/examples/data_formats/JSON/sample01.json +3 -0
  7. data/examples/data_formats/JSON/sample01.svg +36 -0
  8. data/examples/data_formats/JSON/sample02.json +6 -0
  9. data/examples/data_formats/JSON/sample02.svg +128 -0
  10. data/examples/data_formats/JSON/sample03.json +88 -0
  11. data/examples/general/calc_iter1/README.md +26 -0
  12. data/examples/general/calc_iter2/README.md +55 -0
  13. data/examples/general/general_examples.md +37 -0
  14. data/examples/tokenizer/README.md +46 -0
  15. data/examples/tokenizer/loxxy_raw_scanner.rex +98 -0
  16. data/examples/tokenizer/loxxy_raw_scanner.rex.rb +256 -0
  17. data/examples/tokenizer/loxxy_tokenizer.rb +94 -0
  18. data/examples/tokenizer/run_tokenizer.rb +29 -0
  19. data/lib/rley/constants.rb +1 -1
  20. data/lib/rley/lexical/literal.rb +29 -0
  21. data/lib/rley/lexical/token.rb +7 -4
  22. data/lib/rley/notation/all_notation_nodes.rb +3 -1
  23. data/lib/rley/notation/ast_builder.rb +185 -191
  24. data/lib/rley/notation/ast_node.rb +5 -5
  25. data/lib/rley/notation/ast_visitor.rb +3 -1
  26. data/lib/rley/notation/grammar.rb +1 -1
  27. data/lib/rley/notation/grammar_builder.rb +87 -33
  28. data/lib/rley/notation/grouping_node.rb +1 -1
  29. data/lib/rley/notation/parser.rb +56 -56
  30. data/lib/rley/notation/sequence_node.rb +3 -3
  31. data/lib/rley/notation/symbol_node.rb +2 -2
  32. data/lib/rley/notation/tokenizer.rb +3 -15
  33. data/lib/rley/parse_rep/ast_base_builder.rb +35 -4
  34. data/lib/rley/parser/gfg_chart.rb +5 -4
  35. data/lib/rley/parser/gfg_earley_parser.rb +1 -1
  36. data/lib/rley/syntax/base_grammar_builder.rb +8 -2
  37. data/lib/rley/syntax/match_closest.rb +7 -7
  38. data/lib/rley.rb +1 -1
  39. data/spec/rley/lexical/literal_spec.rb +33 -0
  40. data/spec/rley/lexical/token_spec.rb +15 -4
  41. data/spec/rley/notation/grammar_builder_spec.rb +57 -50
  42. data/spec/rley/notation/parser_spec.rb +183 -184
  43. data/spec/rley/notation/tokenizer_spec.rb +98 -104
  44. data/spec/rley/parser/dangling_else_spec.rb +20 -20
  45. data/spec/rley/parser/gfg_chart_spec.rb +0 -1
  46. data/spec/rley/parser/gfg_earley_parser_spec.rb +166 -147
  47. data/spec/rley/parser/gfg_parsing_spec.rb +2 -2
  48. data/spec/rley/syntax/base_grammar_builder_spec.rb +7 -8
  49. data/spec/rley/syntax/grammar_spec.rb +6 -9
  50. data/spec/rley/syntax/match_closest_spec.rb +4 -4
  51. metadata +19 -9
  52. data/lib/rley/parser/parse_tracer.rb +0 -103
  53. data/lib/rley/syntax/literal.rb +0 -20
  54. data/lib/rley/syntax/verbatim_symbol.rb +0 -27
  55. data/spec/rley/syntax/literal_spec.rb +0 -31
  56. 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/verbatim_symbol'
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::VerbatimSymbol.new('+') }
57
- let(:star) { Syntax::VerbatimSymbol.new('*') }
58
- let(:integer) do
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', # Initialization
200
- 'P => . S | 0', # start rule
201
- '.S | 0', # call rule
202
- "S => . S '+' M | 0", # start rule
203
- 'S => . M | 0', # start rule
204
- '.M | 0', # call rule
205
- "M => . M '*' T | 0", # start rule
206
- 'M => . T | 0', # start rule
207
- '.T | 0', # call rule
208
- 'T => . integer | 0' # start rule
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', # scan '2'
217
- 'T. | 0', # exit rule
218
- 'M => T . | 0', # end rule
219
- 'M. | 0', # exit rule
220
- 'S => M . | 0', # end rule
221
- "M => M . '*' T | 0", # end rule
222
- 'S. | 0', # exit rule
223
- 'P => S . | 0', # end rule
224
- "S => S . '+' M | 0", # end rule
225
- 'P. | 0' # exit rule
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
- "S => S '+' . M | 0", # scan '+'
234
- '.M | 2', # call rule
235
- "M => . M '*' T | 2", # start rule
236
- 'M => . T | 2', # start rule
237
- '.T | 2', # call rule
238
- 'T => . integer | 2' # start rule
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', # scan '3'
247
- 'T. | 2', # exit rule
248
- 'M => T . | 2', # end rule
249
- 'M. | 2', # exit rule
250
- "S => S '+' M . | 0", # end rule
251
- "M => M . '*' T | 2", # end rule
252
- 'S. | 0', # exit rule
253
- 'P => S . | 0', # end rule
254
- "S => S . '+' M | 0", # end rule
255
- 'P. | 0' # exit rule
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
- "M => M '*' . T | 2", # scan '*'
263
- '.T | 4', # call rule
264
- 'T => . integer | 4' # entry rule
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', # scan '4'
272
- 'T. | 4', # exit rule
273
- "M => M '*' T . | 2", # end rule
274
- 'M. | 2', # exit rule
275
- "S => S '+' M . | 0", # end rule
276
- "M => M . '*' T | 2", # end rule
277
- 'S. | 0', # exit rule
278
- 'P => S . | 0', # end rule
279
- "S => S . '+' M | 0", # end rule
280
- 'P. | 0' # end rule
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' , # start rule
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' , # end rule
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', # call rule
333
- 'integer => . digit_plus | 2' , # start rule
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' , # end rule
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', # exit rule
347
+ 'sequence. | 0', # exit rule
350
348
  'S => sequence . | 0', # end rule
351
- 'sequence => sequence . comma integer | 0', # rule
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' , # end rule
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', # end rule
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::VerbatimSymbol.new('x')
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', # Initialization
393
- "Ss => . A A 'x' | 0", # start rule
394
- '.A | 0', # call rule
395
- 'A => . | 0', # start rule
396
- 'A. | 0', # exit rule
397
- "Ss => A . A 'x' | 0", # end rule
398
- "Ss => A A . 'x' | 0" # end rule
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
- "Ss => A A 'x' . | 0", # scan 'x'
406
- 'Ss. | 0' # exit rule
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::Literal.new('integer', /[-+]?\d+/)
420
- t_plus = Syntax::VerbatimSymbol.new('+')
421
- t_star = Syntax::VerbatimSymbol.new('*')
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
- "S => . S '+' S | 0", # entry rule
452
- "S => . S '*' S | 0", # entry rule
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
- "S => S . '+' S | 0", # end rule
468
- "S => S . '*' S | 0", # end rule
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
- "S => S '+' . S | 0", # scan '+'
474
+ 'S => S + . S | 0', # scan '+'
477
475
  '.S | 2', # call rule
478
- "S => . S '+' S | 2", # entry rule
479
- "S => . S '*' S | 2", # entry rule
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
- "S => S '+' S . | 0", # end rule
494
- "S => S . '+' S | 2", # end rule
495
- "S => S . '*' S | 2", # end rule
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
- "S => S . '+' S | 0", # end rule
499
- "S => S . '*' S | 0", # end rule
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
- "S => S '*' . S | 2", # scan '*'
508
- "S => S '*' . S | 0", # scan '*'
505
+ 'S => S * . S | 2', # scan '*'
506
+ 'S => S * . S | 0', # scan '*'
509
507
  '.S | 4', # call rule
510
- "S => . S '+' S | 4", # entry rule
511
- "S => . S '*' S | 4", # entry rule
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
- "S => S '*' S . | 2", # end rule
526
- "S => S '*' S . | 0", # end rule
527
- "S => S . '+' S | 4", # end rule
528
- "S => S . '*' S | 4", # end rule
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
- "S => S '+' S . | 0", # end rule
532
- "S => S . '+' S | 2", # end rule
533
- "S => S . '*' S | 2", # end rule
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
- "S => S . '+' S | 0", # end rule
536
- "S => S . '*' S | 0", # end rule
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
- "S => S '*' S . | 2" => ['S. | 4'],
547
- "S => S '*' S . | 0" => ['S. | 4'],
548
- "S => S . '+' S | 4" => ['S. | 4'],
549
- "S => S . '*' S | 4" => ['S. | 4'],
550
- 'S. | 2' => ["S => S '*' S . | 2"],
551
- 'S. | 0' => ["S => S '*' S . | 0", "S => S '+' S . | 0"],
552
- "S => S '+' S . | 0" => ['S. | 2'],
553
- "S => S . '+' S | 2" => ['S. | 2'],
554
- "S => S . '*' S | 2" => ['S. | 2'],
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
- "S => S . '+' S | 0" => ['S. | 0'],
557
- "S => S . '*' S | 0" => ['S. | 0'],
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::VerbatimSymbol.new('a')
819
- t_star = Syntax::VerbatimSymbol.new('*')
820
- t_slash = Syntax::VerbatimSymbol.new('/')
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
- "F => . 'a' | 0" # start rule
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
- "F => 'a' . | 0", # scan 'a'
856
- 'F. | 0', # exit rule
857
- 'E => F . | 0', # end rule
858
- 'E. | 0', # exit rule
859
- 'Z => E . | 0', # end rule
860
- 'E => E . Q F | 0', # end rule
861
- 'Z. | 0', # exit rule
862
- '.Q | 1', # call rule
863
- "Q => . '*' | 1", # start rule
864
- "Q => . '/' | 1", # start rule
865
- 'Q => . | 1', # start rule
866
- 'Q. | 1', # exit rule
867
- 'E => E Q . F | 0', # end rule
868
- '.F | 1', # call rule
869
- "F => . 'a' | 1" # start rule
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
- "F => 'a' . | 1", # scan 'a'
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
- "Q => . '*' | 2", # start rule
885
- "Q => . '/' | 2", # start rule
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
- "F => . 'a' | 2" # start rule
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
- "Q => '/' . | 2", # scan '/'
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
- "F => . 'a' | 3" # entry rule
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
- "F => 'a' . | 3", # scan 'a'
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
- "Q => . '*' | 4", # start rule
919
- "Q => . '/' | 4", # start rule
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
- "F => . 'a' | 4" # entry rule
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
- builder.add_terminals('a')
939
- builder.add_production('S' => 'a S')
940
- builder.add_production('S' => '')
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/verbatim_symbol'
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 = VerbatimSymbol.new('b')
59
- c = Literal.new('c', /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 = VerbatimSymbol.new('b')
71
- c = Literal.new('c', /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 = VerbatimSymbol.new('a')
202
- t_star = VerbatimSymbol.new('*')
203
- t_slash = VerbatimSymbol.new('/')
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)