rley 0.3.04 → 0.3.05

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -3
  3. data/CHANGELOG.md +3 -0
  4. data/Rakefile +30 -30
  5. data/examples/parsers/parsing_L0.rb +1 -1
  6. data/examples/parsers/parsing_L1.rb +1 -1
  7. data/examples/parsers/parsing_abc.rb +1 -1
  8. data/examples/parsers/parsing_ambig.rb +1 -1
  9. data/examples/parsers/parsing_another.rb +1 -1
  10. data/examples/parsers/parsing_b_expr.rb +1 -1
  11. data/examples/parsers/parsing_err_expr.rb +1 -1
  12. data/examples/parsers/parsing_groucho.rb +1 -1
  13. data/examples/parsers/parsing_right_recursive.rb +1 -1
  14. data/examples/parsers/parsing_tricky.rb +1 -1
  15. data/lib/rley/constants.rb +2 -2
  16. data/lib/rley/formatter/base_formatter.rb +0 -2
  17. data/lib/rley/formatter/debug.rb +0 -2
  18. data/lib/rley/formatter/json.rb +1 -3
  19. data/lib/rley/gfg/call_edge.rb +31 -30
  20. data/lib/rley/gfg/edge.rb +22 -23
  21. data/lib/rley/gfg/end_vertex.rb +22 -24
  22. data/lib/rley/gfg/epsilon_edge.rb +20 -21
  23. data/lib/rley/gfg/grm_flow_graph.rb +39 -39
  24. data/lib/rley/gfg/item_vertex.rb +16 -17
  25. data/lib/rley/gfg/non_terminal_vertex.rb +3 -4
  26. data/lib/rley/gfg/return_edge.rb +32 -31
  27. data/lib/rley/gfg/scan_edge.rb +25 -26
  28. data/lib/rley/gfg/shortcut_edge.rb +25 -26
  29. data/lib/rley/gfg/start_vertex.rb +0 -2
  30. data/lib/rley/gfg/vertex.rb +8 -8
  31. data/lib/rley/parse_forest_visitor.rb +113 -115
  32. data/lib/rley/parse_tree_visitor.rb +0 -2
  33. data/lib/rley/parser/base_parser.rb +27 -27
  34. data/lib/rley/parser/chart.rb +14 -14
  35. data/lib/rley/parser/dotted_item.rb +33 -33
  36. data/lib/rley/parser/earley_parser.rb +6 -6
  37. data/lib/rley/parser/gfg_chart.rb +8 -15
  38. data/lib/rley/parser/gfg_earley_parser.rb +15 -13
  39. data/lib/rley/parser/gfg_parsing.rb +26 -22
  40. data/lib/rley/parser/grm_items_builder.rb +3 -2
  41. data/lib/rley/parser/parse_entry.rb +3 -9
  42. data/lib/rley/parser/parse_entry_set.rb +14 -19
  43. data/lib/rley/parser/parse_entry_tracker.rb +56 -56
  44. data/lib/rley/parser/parse_forest_builder.rb +215 -214
  45. data/lib/rley/parser/parse_forest_factory.rb +57 -56
  46. data/lib/rley/parser/parse_state.rb +8 -11
  47. data/lib/rley/parser/parse_state_tracker.rb +56 -56
  48. data/lib/rley/parser/parse_tracer.rb +3 -3
  49. data/lib/rley/parser/parse_tree_builder.rb +10 -10
  50. data/lib/rley/parser/parse_walker_factory.rb +30 -33
  51. data/lib/rley/parser/parsing.rb +8 -8
  52. data/lib/rley/parser/state_set.rb +23 -26
  53. data/lib/rley/ptree/non_terminal_node.rb +1 -1
  54. data/lib/rley/ptree/token_range.rb +2 -2
  55. data/lib/rley/sppf/alternative_node.rb +32 -34
  56. data/lib/rley/sppf/composite_node.rb +27 -27
  57. data/lib/rley/sppf/epsilon_node.rb +26 -27
  58. data/lib/rley/sppf/leaf_node.rb +11 -12
  59. data/lib/rley/sppf/non_terminal_node.rb +37 -38
  60. data/lib/rley/sppf/sppf_node.rb +1 -1
  61. data/lib/rley/sppf/token_node.rb +29 -29
  62. data/lib/rley/syntax/grammar.rb +1 -3
  63. data/lib/rley/syntax/grammar_builder.rb +8 -8
  64. data/lib/rley/syntax/non_terminal.rb +2 -4
  65. data/lib/rley/syntax/production.rb +3 -3
  66. data/lib/rley/syntax/symbol_seq.rb +1 -1
  67. data/spec/rley/gfg/call_edge_spec.rb +50 -51
  68. data/spec/rley/gfg/edge_spec.rb +33 -33
  69. data/spec/rley/gfg/end_vertex_spec.rb +26 -27
  70. data/spec/rley/gfg/epsilon_edge_spec.rb +25 -25
  71. data/spec/rley/gfg/grm_flow_graph_spec.rb +1 -1
  72. data/spec/rley/gfg/item_vertex_spec.rb +3 -4
  73. data/spec/rley/gfg/return_edge_spec.rb +51 -51
  74. data/spec/rley/gfg/scan_edge_spec.rb +32 -30
  75. data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
  76. data/spec/rley/gfg/vertex_spec.rb +3 -3
  77. data/spec/rley/parse_forest_visitor_spec.rb +239 -238
  78. data/spec/rley/parser/dotted_item_spec.rb +1 -1
  79. data/spec/rley/parser/earley_parser_spec.rb +16 -16
  80. data/spec/rley/parser/gfg_earley_parser_spec.rb +30 -31
  81. data/spec/rley/parser/gfg_parsing_spec.rb +11 -10
  82. data/spec/rley/parser/grm_items_builder_spec.rb +2 -2
  83. data/spec/rley/parser/parse_entry_set_spec.rb +4 -4
  84. data/spec/rley/parser/parse_entry_spec.rb +0 -2
  85. data/spec/rley/parser/parse_forest_builder_spec.rb +82 -57
  86. data/spec/rley/parser/parse_forest_factory_spec.rb +84 -82
  87. data/spec/rley/parser/parse_walker_factory_spec.rb +10 -9
  88. data/spec/rley/parser/parsing_spec.rb +0 -1
  89. data/spec/rley/sppf/alternative_node_spec.rb +2 -2
  90. data/spec/rley/sppf/non_terminal_node_spec.rb +0 -1
  91. data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
  92. data/spec/rley/support/expectation_helper.rb +37 -36
  93. data/spec/rley/support/grammar_abc_helper.rb +17 -17
  94. data/spec/rley/support/grammar_b_expr_helper.rb +40 -39
  95. data/spec/rley/support/grammar_helper.rb +2 -1
  96. data/spec/rley/support/{grammar_L0_helper.rb → grammar_l0_helper.rb} +82 -81
  97. data/spec/rley/support/grammar_sppf_helper.rb +24 -25
  98. data/spec/rley/syntax/grammar_spec.rb +1 -1
  99. metadata +2 -2
@@ -1,82 +1,84 @@
1
- require_relative '../../spec_helper'
2
-
3
- require_relative '../../../lib/rley/parser/gfg_earley_parser'
4
-
5
- require_relative '../../../lib/rley/syntax/grammar_builder'
6
- require_relative '../support/grammar_helper'
7
- require_relative '../support/expectation_helper'
8
-
9
- # Load the class under test
10
- require_relative '../../../lib/rley/parser/parse_forest_factory'
11
-
12
- module Rley # Open this namespace to avoid module qualifier prefixes
13
- module Parser
14
- describe ParseForestFactory do
15
- include GrammarHelper # Mix-in with token factory method
16
- include ExpectationHelper # Mix-in with expectation on parse entry sets
17
-
18
- let(:sample_grammar) do
19
- # Grammar based on paper from Elisabeth Scott
20
- # "SPPF=Style Parsing From Earley Recognizers" in
21
- # Notes in Theoretical Computer Science 203, (2008), pp. 53-67
22
- # contains a hidden left recursion and a cycle
23
- builder = Syntax::GrammarBuilder.new
24
- builder.add_terminals('a', 'b')
25
- builder.add_production('Phi' => %'S')
26
- builder.add_production('S' => %w[A T])
27
- builder.add_production('S' => %w[a T])
28
- builder.add_production('A' => 'a')
29
- builder.add_production('A' => %w[B A])
30
- builder.add_production('B' => [])
31
- builder.add_production('T' => %w( b b b))
32
- builder.grammar
33
- end
34
-
35
- let(:sample_tokens) do
36
- build_token_sequence(%w(a b b b), sample_grammar)
37
- end
38
-
39
- let(:sample_result) do
40
- parser = Parser::GFGEarleyParser.new(sample_grammar)
41
- parser.parse(sample_tokens)
42
- end
43
-
44
-
45
- subject do
46
- ParseForestFactory.new(sample_result)
47
- end
48
-
49
- # Emit a text representation of the current path.
50
- def path_to_s()
51
- text_parts = subject.curr_path.map { |path_element| path_element.to_string(0) }
52
- return text_parts.join('/')
53
- end
54
-
55
-
56
- context 'Initialization:' do
57
- it 'should be created with a GFGParsing' do
58
- expect { ParseForestFactory.new(sample_result) }.not_to raise_error
59
- end
60
-
61
- it 'should know the parse result' do
62
- expect(subject.parsing).to eq(sample_result)
63
- end
64
- end
65
-
66
- context 'Parse forest construction' do
67
- it 'should build a parse forest' do
68
- forest = subject.build_parse_forest
69
- expect(forest).to be_kind_of(SPPF::ParseForest)
70
- =begin
71
- require 'yaml'
72
- require_relative '../../../exp/lab/forest_representation'
73
- File.open("forest.yml", "w") { |f| YAML.dump(forest, f) }
74
- pen = ForestRepresentation.new
75
- pen.generate_graph(forest, File.open("forest.dot", "w"))
76
- =end
77
- end
78
- end # context
79
- end # describe
80
- end # module
81
- end # module
82
- # End of file
1
+ require_relative '../../spec_helper'
2
+
3
+ require_relative '../../../lib/rley/parser/gfg_earley_parser'
4
+
5
+ require_relative '../../../lib/rley/syntax/grammar_builder'
6
+ require_relative '../support/grammar_helper'
7
+ require_relative '../support/expectation_helper'
8
+
9
+ # Load the class under test
10
+ require_relative '../../../lib/rley/parser/parse_forest_factory'
11
+
12
+ module Rley # Open this namespace to avoid module qualifier prefixes
13
+ module Parser
14
+ describe ParseForestFactory do
15
+ include GrammarHelper # Mix-in with token factory method
16
+ include ExpectationHelper # Mix-in with expectation on parse entry sets
17
+
18
+ let(:sample_grammar) do
19
+ # Grammar based on paper from Elisabeth Scott
20
+ # "SPPF=Style Parsing From Earley Recognizers" in
21
+ # Notes in Theoretical Computer Science 203, (2008), pp. 53-67
22
+ # contains a hidden left recursion and a cycle
23
+ builder = Syntax::GrammarBuilder.new
24
+ builder.add_terminals('a', 'b')
25
+ builder.add_production('Phi' => 'S')
26
+ builder.add_production('S' => %w(A T))
27
+ builder.add_production('S' => %w(a T))
28
+ builder.add_production('A' => 'a')
29
+ builder.add_production('A' => %w(B A))
30
+ builder.add_production('B' => [])
31
+ builder.add_production('T' => %w(b b b))
32
+ builder.grammar
33
+ end
34
+
35
+ let(:sample_tokens) do
36
+ build_token_sequence(%w(a b b b), sample_grammar)
37
+ end
38
+
39
+ let(:sample_result) do
40
+ parser = Parser::GFGEarleyParser.new(sample_grammar)
41
+ parser.parse(sample_tokens)
42
+ end
43
+
44
+
45
+ subject do
46
+ ParseForestFactory.new(sample_result)
47
+ end
48
+
49
+ # Emit a text representation of the current path.
50
+ def path_to_s()
51
+ text_parts = subject.curr_path.map do |path_element|
52
+ path_element.to_string(0)
53
+ end
54
+ return text_parts.join('/')
55
+ end
56
+
57
+
58
+ context 'Initialization:' do
59
+ it 'should be created with a GFGParsing' do
60
+ expect { ParseForestFactory.new(sample_result) }.not_to raise_error
61
+ end
62
+
63
+ it 'should know the parse result' do
64
+ expect(subject.parsing).to eq(sample_result)
65
+ end
66
+ end
67
+
68
+ context 'Parse forest construction' do
69
+ it 'should build a parse forest' do
70
+ forest = subject.build_parse_forest
71
+ expect(forest).to be_kind_of(SPPF::ParseForest)
72
+ =begin
73
+ require 'yaml'
74
+ require_relative '../../../exp/lab/forest_representation'
75
+ File.open("forest.yml", "w") { |f| YAML.dump(forest, f) }
76
+ pen = ForestRepresentation.new
77
+ pen.generate_graph(forest, File.open("forest.dot", "w"))
78
+ =end
79
+ end
80
+ end # context
81
+ end # describe
82
+ end # module
83
+ end # module
84
+ # End of file
@@ -45,13 +45,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
45
45
  # contains a hidden left recursion and a cycle
46
46
  builder = Syntax::GrammarBuilder.new
47
47
  builder.add_terminals('a', 'b')
48
- builder.add_production('Phi' => %'S')
49
- builder.add_production('S' => %w[A T])
50
- builder.add_production('S' => %w[a T])
48
+ builder.add_production('Phi' => 'S')
49
+ builder.add_production('S' => %w(A T))
50
+ builder.add_production('S' => %w(a T))
51
51
  builder.add_production('A' => 'a')
52
- builder.add_production('A' => %w[B A])
52
+ builder.add_production('A' => %w(B A))
53
53
  builder.add_production('B' => [])
54
- builder.add_production('T' => %w( b b b))
54
+ builder.add_production('T' => %w(b b b))
55
55
  builder.grammar
56
56
  end
57
57
 
@@ -77,7 +77,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
77
77
 
78
78
  context 'Parse graph traversal:' do
79
79
  it 'should create an Enumerator as a walker' do
80
- expect(subject.build_walker(accept_entry, accept_index)).to be_kind_of(Enumerator)
80
+ entry = accept_entry
81
+ index = accept_index
82
+ expect(subject.build_walker(entry, index)).to be_kind_of(Enumerator)
81
83
  end
82
84
 
83
85
  it 'should return the accepting parse entry in the first place' do
@@ -247,11 +249,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
247
249
  walker = subject.build_walker(accept_entry, accept_index)
248
250
  37.times { walker.next }
249
251
 
250
- expect{ walker.next }.to raise_error(StopIteration)
252
+ expect { walker.next }.to raise_error(StopIteration)
251
253
  end
252
-
253
254
  end # context
254
255
  end # describe
255
256
  end # module
256
257
  end # module
257
- # End of file
258
+ # End of file
@@ -170,7 +170,6 @@ SNIPPET
170
170
  return [state_tracker, builder]
171
171
  end
172
172
 
173
- # Spiff
174
173
  it 'should create the root of a parse tree' do
175
174
  (state_tracker, builder) = prepare_parse_tree(subject)
176
175
  # The root node should correspond to the start symbol and
@@ -33,7 +33,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
33
33
 
34
34
  context 'Construction:' do
35
35
  it 'should be created with a item vertex and a token range' do
36
- expect { AlternativeNode.new(sample_vertex, sample_range) }.not_to raise_error
36
+ expect { AlternativeNode.new(sample_vertex, sample_range) }
37
+ .not_to raise_error
37
38
  end
38
39
  end
39
40
 
@@ -64,7 +65,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
64
65
  expect(subject.to_string(0)).to eq('Alt(sentence => A B C .)[0, 3]')
65
66
  end
66
67
  end # context
67
-
68
68
  end # describe
69
69
  end # module
70
70
  end # module
@@ -56,7 +56,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
56
56
  expect(subject.to_string(0)).to eq('VP[0, 3]')
57
57
  end
58
58
  end # context
59
-
60
59
  end # describe
61
60
  end # module
62
61
  end # module
@@ -26,7 +26,7 @@ module AmbiguousGrammarHelper
26
26
  terminal = aGrammar.name2symbol['id']
27
27
  else
28
28
  msg = "Unknown input text '#{lexeme}'"
29
- fail StandardError, msg
29
+ raise StandardError, msg
30
30
  end
31
31
  Rley::Parser::Token.new(lexeme, terminal)
32
32
  end
@@ -1,36 +1,37 @@
1
- # Load the builder class
2
- require_relative '../../../lib/rley/parser/token'
3
-
4
-
5
- # Mixin module implementing expectation helper methods.
6
- module ExpectationHelper
7
- # Helper method. Compare the data from all the parse entries
8
- # of a given ParseEntrySet with an array of expectation strings.
9
- def compare_entry_texts(anEntrySet, expectations)
10
- (0...expectations.size).each do |i|
11
- expect(anEntrySet.entries[i].to_s).to eq(expectations[i])
12
- end
13
- end
14
-
15
- # Helper method. Compare the antecedents from all the parse entries
16
- # of a given ParseEntrySet at given position with a Hash of the form:
17
- # consequent label => [ antecedent label(s) ]
18
- def check_antecedence(aParsing, aPosition, expectations)
19
- entry_set = aParsing.chart[aPosition]
20
-
21
- expectations.each do |consequent_label, antecedent_labels|
22
- consequent = entry_set.entries.find do |entry|
23
- entry.to_s == consequent_label
24
- end
25
- actual_antecedents = aParsing.antecedence.fetch(consequent)
26
- expect(actual_antecedents.map(&:to_s)).to eq(antecedent_labels)
27
- end
28
- end
29
-
30
-
31
- def expected_terminals(anEntrySet, termNames)
32
- terminals = anEntrySet.expected_terminals
33
- actual_names = terminals.map(&:name)
34
- expect(actual_names.sort).to eq(termNames.sort)
35
- end
36
- end # module
1
+ # Load the builder class
2
+ require_relative '../../../lib/rley/parser/token'
3
+
4
+
5
+ # Mixin module implementing expectation helper methods.
6
+ module ExpectationHelper
7
+ # Helper method. Compare the data from all the parse entries
8
+ # of a given ParseEntrySet with an array of expectation strings.
9
+ def compare_entry_texts(anEntrySet, expectations)
10
+ (0...expectations.size).each do |i|
11
+ expect(anEntrySet.entries[i].to_s).to eq(expectations[i])
12
+ end
13
+ end
14
+
15
+ # Helper method. Compare the antecedents from all the parse entries
16
+ # of a given ParseEntrySet at given position with a Hash of the form:
17
+ # consequent label => [ antecedent label(s) ]
18
+ def check_antecedence(aParsing, aPosition, expectations)
19
+ entry_set = aParsing.chart[aPosition]
20
+
21
+ expectations.each do |consequent_label, antecedent_labels|
22
+ consequent = entry_set.entries.find do |entry|
23
+ entry.to_s == consequent_label
24
+ end
25
+ actual_antecedents = aParsing.antecedence.fetch(consequent)
26
+ expect(actual_antecedents.map(&:to_s)).to eq(antecedent_labels)
27
+ end
28
+ end
29
+
30
+
31
+ def expected_terminals(anEntrySet, termNames)
32
+ terminals = anEntrySet.expected_terminals
33
+ actual_names = terminals.map(&:name)
34
+ expect(actual_names.sort).to eq(termNames.sort)
35
+ end
36
+ end # module
37
+ # End of file
@@ -1,17 +1,17 @@
1
- # Load the builder class
2
- require_relative '../../../lib/rley/syntax/grammar_builder'
3
-
4
-
5
- module GrammarABCHelper
6
- # Factory method. Creates a grammar builder for a simple grammar.
7
- # (based on example in N. Wirth "Compiler Construction" book, p. 6)
8
- def grammar_abc_builder()
9
- builder = Rley::Syntax::GrammarBuilder.new
10
- builder.add_terminals('a', 'b', 'c')
11
- builder.add_production('S' => 'A')
12
- builder.add_production('A' => %w(a A c))
13
- builder.add_production('A' => 'b')
14
-
15
- return builder
16
- end
17
- end # module
1
+ # Load the builder class
2
+ require_relative '../../../lib/rley/syntax/grammar_builder'
3
+
4
+ module GrammarABCHelper
5
+ # Factory method. Creates a grammar builder for a simple grammar.
6
+ # (based on example in N. Wirth "Compiler Construction" book, p. 6)
7
+ def grammar_abc_builder()
8
+ builder = Rley::Syntax::GrammarBuilder.new
9
+ builder.add_terminals('a', 'b', 'c')
10
+ builder.add_production('S' => 'A')
11
+ builder.add_production('A' => %w(a A c))
12
+ builder.add_production('A' => 'b')
13
+
14
+ return builder
15
+ end
16
+ end # module
17
+ # End of file
@@ -1,39 +1,40 @@
1
- # Load the builder class
2
- require_relative '../../../lib/rley/syntax/grammar_builder'
3
- require_relative '../../../lib/rley/parser/token'
4
-
5
-
6
- module GrammarBExprHelper
7
- # Factory method. Creates a grammar builder for a basic arithmetic
8
- # expression grammar.
9
- # (based on the article about Earley's algorithm in Wikipedia)
10
- def grammar_expr_builder()
11
- builder = Rley::Syntax::GrammarBuilder.new
12
- builder.add_terminals('+', '*', 'integer')
13
- builder.add_production('P' => 'S')
14
- builder.add_production('S' => %w(S + M))
15
- builder.add_production('S' => 'M')
16
- builder.add_production('M' => %w(M * T))
17
- builder.add_production('M' => 'T')
18
- builder.add_production('T' => 'integer')
19
- builder
20
- end
21
-
22
- # Basic expression tokenizer
23
- def expr_tokenizer(aText, aGrammar)
24
- tokens = aText.scan(/\S+/).map do |lexeme|
25
- case lexeme
26
- when '+', '*'
27
- terminal = aGrammar.name2symbol[lexeme]
28
- when /^[-+]?\d+$/
29
- terminal = aGrammar.name2symbol['integer']
30
- else
31
- msg = "Unknown input text '#{lexeme}'"
32
- fail StandardError, msg
33
- end
34
- Rley::Parser::Token.new(lexeme, terminal)
35
- end
36
-
37
- return tokens
38
- end
39
- end # module
1
+ # Load the builder class
2
+ require_relative '../../../lib/rley/syntax/grammar_builder'
3
+ require_relative '../../../lib/rley/parser/token'
4
+
5
+
6
+ module GrammarBExprHelper
7
+ # Factory method. Creates a grammar builder for a basic arithmetic
8
+ # expression grammar.
9
+ # (based on the article about Earley's algorithm in Wikipedia)
10
+ def grammar_expr_builder()
11
+ builder = Rley::Syntax::GrammarBuilder.new
12
+ builder.add_terminals('+', '*', 'integer')
13
+ builder.add_production('P' => 'S')
14
+ builder.add_production('S' => %w(S + M))
15
+ builder.add_production('S' => 'M')
16
+ builder.add_production('M' => %w(M * T))
17
+ builder.add_production('M' => 'T')
18
+ builder.add_production('T' => 'integer')
19
+ builder
20
+ end
21
+
22
+ # Basic expression tokenizer
23
+ def expr_tokenizer(aText, aGrammar)
24
+ tokens = aText.scan(/\S+/).map do |lexeme|
25
+ case lexeme
26
+ when '+', '*'
27
+ terminal = aGrammar.name2symbol[lexeme]
28
+ when /^[-+]?\d+$/
29
+ terminal = aGrammar.name2symbol['integer']
30
+ else
31
+ msg = "Unknown input text '#{lexeme}'"
32
+ raise StandardError, msg
33
+ end
34
+ Rley::Parser::Token.new(lexeme, terminal)
35
+ end
36
+
37
+ return tokens
38
+ end
39
+ end # module
40
+ # End of file
@@ -25,4 +25,5 @@ module GrammarHelper
25
25
 
26
26
  return tokens.flatten
27
27
  end
28
- end # module
28
+ end # module
29
+ # End of file