rley 0.4.01 → 0.4.02

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/LICENSE.txt +2 -2
  4. data/README.md +3 -3
  5. data/examples/NLP/mini_en_demo.rb +1 -1
  6. data/examples/data_formats/JSON/JSON_demo.rb +1 -0
  7. data/examples/data_formats/JSON/JSON_lexer.rb +4 -4
  8. data/examples/general/calc/calc_lexer.rb +2 -2
  9. data/lib/rley.rb +1 -1
  10. data/lib/rley/constants.rb +1 -1
  11. data/lib/rley/formatter/debug.rb +2 -2
  12. data/lib/rley/formatter/json.rb +4 -4
  13. data/lib/rley/parse_tree_visitor.rb +9 -9
  14. data/lib/rley/parser/base_parser.rb +1 -1
  15. data/lib/rley/parser/gfg_parsing.rb +9 -0
  16. data/lib/rley/parser/parse_tree_builder.rb +176 -126
  17. data/lib/rley/parser/parse_tree_factory.rb +57 -0
  18. data/lib/rley/ptree/non_terminal_node.rb +10 -9
  19. data/lib/rley/ptree/parse_tree_node.rb +10 -5
  20. data/lib/rley/ptree/terminal_node.rb +14 -6
  21. data/lib/rley/sppf/sppf_node.rb +2 -2
  22. data/lib/rley/{parser → tokens}/token.rb +1 -4
  23. data/lib/rley/{ptree → tokens}/token_range.rb +1 -1
  24. data/spec/rley/formatter/debug_spec.rb +16 -16
  25. data/spec/rley/formatter/json_spec.rb +8 -8
  26. data/spec/rley/parse_forest_visitor_spec.rb +1 -1
  27. data/spec/rley/parse_tree_visitor_spec.rb +28 -28
  28. data/spec/rley/parser/error_reason_spec.rb +3 -3
  29. data/spec/rley/parser/gfg_chart_spec.rb +2 -2
  30. data/spec/rley/parser/gfg_earley_parser_spec.rb +2 -2
  31. data/spec/rley/parser/gfg_parsing_spec.rb +2 -2
  32. data/spec/rley/parser/groucho_spec.rb +1 -1
  33. data/spec/rley/parser/parse_tracer_spec.rb +2 -2
  34. data/spec/rley/parser/parse_tree_builder_spec.rb +213 -140
  35. data/spec/rley/parser/parse_tree_factory_spec.rb +85 -0
  36. data/spec/rley/parser/parse_walker_factory_spec.rb +11 -10
  37. data/spec/rley/ptree/non_terminal_node_spec.rb +23 -20
  38. data/spec/rley/ptree/terminal_node_spec.rb +7 -12
  39. data/spec/rley/sppf/alternative_node_spec.rb +2 -2
  40. data/spec/rley/sppf/non_terminal_node_spec.rb +2 -2
  41. data/spec/rley/support/ambiguous_grammar_helper.rb +2 -2
  42. data/spec/rley/support/expectation_helper.rb +1 -1
  43. data/spec/rley/support/grammar_ambig01_helper.rb +2 -2
  44. data/spec/rley/support/grammar_b_expr_helper.rb +2 -2
  45. data/spec/rley/support/grammar_helper.rb +3 -3
  46. data/spec/rley/support/grammar_l0_helper.rb +2 -2
  47. data/spec/rley/support/grammar_pb_helper.rb +2 -2
  48. data/spec/rley/{ptree → tokens}/token_range_spec.rb +2 -2
  49. data/spec/rley/{parser → tokens}/token_spec.rb +2 -2
  50. metadata +11 -17
  51. data/lib/rley/parser/chart.rb +0 -82
  52. data/lib/rley/parser/earley_parser.rb +0 -203
  53. data/lib/rley/parser/parsing.rb +0 -265
  54. data/spec/rley/parser/chart_spec.rb +0 -120
  55. data/spec/rley/parser/earley_parser_spec.rb +0 -710
  56. data/spec/rley/parser/parsing_spec.rb +0 -408
@@ -0,0 +1,57 @@
1
+ require_relative 'parse_walker_factory'
2
+ require_relative 'parse_tree_builder'
3
+
4
+ module Rley # This module is used as a namespace
5
+ module Parser # This module is used as a namespace
6
+ # Utility class that helps to create a ParseTree from
7
+ # a given Parsing object.
8
+ class ParseTreeFactory
9
+ # Link to Parsing object (= results of recognizer)
10
+ attr_reader(:parsing)
11
+
12
+
13
+ def initialize(aParsingResult)
14
+ @parsing = aParsingResult
15
+ end
16
+
17
+ # Factory that produces the parse tree
18
+ def build_parse_tree()
19
+ a_walker = walker(parsing)
20
+ a_builder = builder(parsing)
21
+
22
+ begin
23
+ loop do
24
+ event = a_walker.next
25
+ # puts "EVENT #{event[0]} #{event[1]}"
26
+ a_builder.receive_event(*event)
27
+ end
28
+ rescue StopIteration
29
+ # Do nothing
30
+ end
31
+
32
+ return a_builder.tree
33
+ end
34
+
35
+
36
+ private
37
+
38
+ # Create a Parsing walker, that is, an object
39
+ # that will iterate over the relevant nodes (= parsing entries)
40
+ # of a GFGParsing
41
+ def walker(aParseResult)
42
+ walker_factory = ParseWalkerFactory.new
43
+ accept_entry = aParseResult.accepting_entry
44
+ accept_index = aParseResult.chart.last_index
45
+ walker_factory.build_walker(accept_entry, accept_index)
46
+ end
47
+
48
+ # Create a Builder, that is, an object
49
+ # that will create piece by piece the forest
50
+ def builder(aParseResult)
51
+ ParseTreeBuilder.new(aParseResult.tokens)
52
+ end
53
+ end # class
54
+ end # module
55
+ end # module
56
+
57
+ # End of file
@@ -3,17 +3,18 @@ require_relative 'parse_tree_node' # Load superclass
3
3
  module Rley # This module is used as a namespace
4
4
  module PTree # This module is used as a namespace
5
5
  class NonTerminalNode < ParseTreeNode
6
- # Link to the input token
7
- attr_reader(:children)
6
+ # Array of sub-nodes.
7
+ attr_reader(:subnodes)
8
8
 
9
9
  def initialize(aSymbol, aRange)
10
10
  super(aSymbol, aRange)
11
- @children = []
11
+ @subnodes = []
12
12
  end
13
13
 
14
- # @param aChildNode [ParseTreeNode-like] a child node.
15
- def add_child(aChildNode)
16
- children << aChildNode
14
+ # Pre-pend the given subnode in front of the list of subnodes
15
+ # @param aSubnode [ParseTreeNode-like] a child node.
16
+ def add_subnode(aSubnode)
17
+ subnodes.unshift(aSubnode)
17
18
  end
18
19
 
19
20
  # Emit a (formatted) string representation of the node.
@@ -22,11 +23,11 @@ module Rley # This module is used as a namespace
22
23
  connector = '+- '
23
24
  selfie = super(indentation)
24
25
  prefix = "\n" + (' ' * connector.size * indentation) + connector
25
- children_repr = children.reduce('') do |sub_result, child|
26
- sub_result << prefix + child.to_string(indentation + 1)
26
+ subnodes_repr = subnodes.reduce('') do |sub_result, subnode|
27
+ sub_result << prefix + subnode.to_string(indentation + 1)
27
28
  end
28
29
 
29
- return selfie + children_repr
30
+ return selfie + subnodes_repr
30
31
  end
31
32
 
32
33
  # Part of the 'visitee' role in Visitor design pattern.
@@ -1,4 +1,4 @@
1
- require_relative 'token_range'
1
+ require_relative '../tokens/token_range'
2
2
 
3
3
  module Rley # This module is used as a namespace
4
4
  module PTree # This module is used as a namespace
@@ -11,19 +11,24 @@ module Rley # This module is used as a namespace
11
11
 
12
12
  def initialize(aSymbol, aRange)
13
13
  @symbol = aSymbol
14
- @range = TokenRange.new(aRange)
14
+ @range = Tokens::TokenRange.new(aRange)
15
15
  end
16
-
16
+
17
17
  def range=(aRange)
18
18
  range.assign(aRange)
19
19
  end
20
-
20
+
21
21
  # Emit a (formatted) string representation of the node.
22
22
  # Mainly used for diagnosis/debugging purposes.
23
23
  def to_string(indentation)
24
-
25
24
  return "#{symbol.name}#{range.to_string(indentation)}"
26
25
  end
26
+
27
+ # Emit a short string representation of the node.
28
+ # Mainly used for diagnosis/debugging purposes.
29
+ def to_s()
30
+ return "#{symbol.name}#{range.to_string(0)}"
31
+ end
27
32
  end # class
28
33
  end # module
29
34
  end # module
@@ -4,24 +4,32 @@ module Rley # This module is used as a namespace
4
4
  module PTree # This module is used as a namespace
5
5
  class TerminalNode < ParseTreeNode
6
6
  # Link to the input token
7
- attr(:token, true)
7
+ attr_reader(:token)
8
8
 
9
- def initialize(aTerminalSymbol, aRange)
10
- super(aTerminalSymbol, aRange)
9
+ # aPosition is the position of the token in the input stream.
10
+ def initialize(aToken, aPos)
11
+ range = aPos.kind_of?(Fixnum) ? { low: aPos, high: aPos + 1 } : aPos
12
+ super(aToken.terminal, range)
13
+ @token = aToken
11
14
  end
12
15
 
13
16
  # Emit a (formatted) string representation of the node.
14
17
  # Mainly used for diagnosis/debugging purposes.
15
18
  def to_string(indentation)
16
- value = token.nil? ? '(nil)' : token.lexeme
17
- super(indentation) + ": '#{value}'"
19
+ return super + ": '#{token.lexeme}'"
18
20
  end
21
+
22
+ # Emit a short string representation of the node.
23
+ # Mainly used for diagnosis/debugging purposes.
24
+ def to_s()
25
+ return super + ": '#{token.lexeme}'"
26
+ end
19
27
 
20
28
  # Part of the 'visitee' role in Visitor design pattern.
21
29
  # @param aVisitor[ParseTreeVisitor] the visitor
22
30
  def accept(aVisitor)
23
31
  aVisitor.visit_terminal(self)
24
- end
32
+ end
25
33
  end # class
26
34
  end # module
27
35
  end # module
@@ -1,4 +1,4 @@
1
- require_relative '../ptree/token_range'
1
+ require_relative '../tokens/token_range'
2
2
 
3
3
  module Rley # This module is used as a namespace
4
4
  module SPPF # This module is used as a namespace
@@ -10,7 +10,7 @@ module Rley # This module is used as a namespace
10
10
  attr_reader(:range)
11
11
 
12
12
  def initialize(aRange)
13
- @range = PTree::TokenRange.new(aRange)
13
+ @range = Tokens::TokenRange.new(aRange)
14
14
  end
15
15
 
16
16
  # Return the origin (= lower bound of the range
@@ -1,8 +1,5 @@
1
- require_relative '../syntax/grammar'
2
- require_relative 'dotted_item'
3
-
4
1
  module Rley # This module is used as a namespace
5
- module Parser # This module is used as a namespace
2
+ module Tokens # This module is used as a namespace
6
3
  class Token
7
4
  attr_reader(:lexeme)
8
5
  attr_reader(:terminal)
@@ -1,5 +1,5 @@
1
1
  module Rley # This module is used as a namespace
2
- module PTree # This module is used as a namespace
2
+ module Tokens # This module is used as a namespace
3
3
  # A token range (also called an extent) represents an interval
4
4
  # of token positions that is matched by a given grammar symbol.
5
5
  # For instance consider the expression E: 3 + 11,
@@ -2,8 +2,8 @@ require_relative '../../spec_helper'
2
2
  require 'stringio'
3
3
 
4
4
  require_relative '../support/grammar_abc_helper'
5
- require_relative '../../../lib/rley/parser/token'
6
- require_relative '../../../lib/rley/parser/earley_parser'
5
+ require_relative '../../../lib/rley/tokens/token'
6
+ require_relative '../../../lib/rley/parser/gfg_earley_parser'
7
7
  require_relative '../../../lib/rley/ptree/parse_tree'
8
8
  require_relative '../../../lib/rley/parse_tree_visitor'
9
9
  # Load the class under test
@@ -30,11 +30,11 @@ module Rley # Re-open the module to get rid of qualified names
30
30
  # for the language specified by gramma_abc
31
31
  let(:grm_abc_tokens1) do
32
32
  [
33
- Parser::Token.new('a', a_),
34
- Parser::Token.new('a', a_),
35
- Parser::Token.new('b', b_),
36
- Parser::Token.new('c', c_),
37
- Parser::Token.new('c', c_)
33
+ Tokens::Token.new('a', a_),
34
+ Tokens::Token.new('a', a_),
35
+ Tokens::Token.new('b', b_),
36
+ Tokens::Token.new('c', c_),
37
+ Tokens::Token.new('c', c_)
38
38
  ]
39
39
  end
40
40
 
@@ -51,7 +51,7 @@ module Rley # Re-open the module to get rid of qualified names
51
51
  # +- c[4,5]
52
52
  # Capital letters represent non-terminal nodes
53
53
  let(:grm_abc_ptree1) do
54
- parser = Parser::EarleyParser.new(grammar_abc)
54
+ parser = Parser::GFGEarleyParser.new(grammar_abc)
55
55
  parse_result = parser.parse(grm_abc_tokens1)
56
56
  parse_result.parse_tree
57
57
  end
@@ -79,30 +79,30 @@ module Rley # Re-open the module to get rid of qualified names
79
79
  expectations = <<-SNIPPET
80
80
  before_ptree
81
81
  before_non_terminal
82
- before_children
82
+ before_subnodes
83
83
  before_non_terminal
84
- before_children
84
+ before_subnodes
85
85
  before_terminal
86
86
  after_terminal
87
87
  before_non_terminal
88
- before_children
88
+ before_subnodes
89
89
  before_terminal
90
90
  after_terminal
91
91
  before_non_terminal
92
- before_children
92
+ before_subnodes
93
93
  before_terminal
94
94
  after_terminal
95
- after_children
95
+ after_subnodes
96
96
  after_non_terminal
97
97
  before_terminal
98
98
  after_terminal
99
- after_children
99
+ after_subnodes
100
100
  after_non_terminal
101
101
  before_terminal
102
102
  after_terminal
103
- after_children
103
+ after_subnodes
104
104
  after_non_terminal
105
- after_children
105
+ after_subnodes
106
106
  after_non_terminal
107
107
  after_ptree
108
108
  SNIPPET
@@ -2,8 +2,8 @@ require_relative '../../spec_helper'
2
2
  require 'stringio'
3
3
 
4
4
  require_relative '../support/grammar_abc_helper'
5
- require_relative '../../../lib/rley/parser/token'
6
- require_relative '../../../lib/rley/parser/earley_parser'
5
+ require_relative '../../../lib/rley/tokens/token'
6
+ require_relative '../../../lib/rley/parser/gfg_earley_parser'
7
7
  require_relative '../../../lib/rley/ptree/parse_tree'
8
8
  require_relative '../../../lib/rley/parse_tree_visitor'
9
9
  # Load the class under test
@@ -30,11 +30,11 @@ module Rley # Re-open the module to get rid of qualified names
30
30
  # for the language specified by gramma_abc
31
31
  let(:grm_abc_tokens1) do
32
32
  [
33
- Parser::Token.new('a', a_),
34
- Parser::Token.new('a', a_),
35
- Parser::Token.new('b', b_),
36
- Parser::Token.new('c', c_),
37
- Parser::Token.new('c', c_)
33
+ Tokens::Token.new('a', a_),
34
+ Tokens::Token.new('a', a_),
35
+ Tokens::Token.new('b', b_),
36
+ Tokens::Token.new('c', c_),
37
+ Tokens::Token.new('c', c_)
38
38
  ]
39
39
  end
40
40
 
@@ -51,7 +51,7 @@ module Rley # Re-open the module to get rid of qualified names
51
51
  # +- c[4,5]
52
52
  # Capital letters represent non-terminal nodes
53
53
  let(:grm_abc_ptree1) do
54
- parser = Parser::EarleyParser.new(grammar_abc)
54
+ parser = Parser::GFGEarleyParser.new(grammar_abc)
55
55
  parse_result = parser.parse(grm_abc_tokens1)
56
56
  parse_result.parse_tree
57
57
  end
@@ -2,7 +2,7 @@ require_relative '../spec_helper'
2
2
 
3
3
  require_relative './support/grammar_helper'
4
4
  require_relative './support/grammar_sppf_helper'
5
- require_relative '../../lib/rley/parser/token'
5
+ require_relative '../../lib/rley/tokens/token'
6
6
  require_relative '../../lib/rley/parser/gfg_earley_parser'
7
7
  require_relative '../../lib/rley/sppf/non_terminal_node'
8
8
  require_relative '../../lib/rley/sppf/parse_forest'
@@ -1,8 +1,8 @@
1
1
  require_relative '../spec_helper'
2
2
 
3
3
  require_relative './support/grammar_abc_helper'
4
- require_relative '../../lib/rley/parser/token'
5
- require_relative '../../lib/rley/parser/earley_parser'
4
+ require_relative '../../lib/rley/tokens/token'
5
+ require_relative '../../lib/rley/parser/gfg_earley_parser'
6
6
  # Load the class under test
7
7
  require_relative '../../lib/rley/parse_tree_visitor'
8
8
 
@@ -24,11 +24,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
24
24
  # for the language specified by gramma_abc
25
25
  let(:grm_abc_tokens1) do
26
26
  [
27
- Parser::Token.new('a', a_),
28
- Parser::Token.new('a', a_),
29
- Parser::Token.new('b', b_),
30
- Parser::Token.new('c', c_),
31
- Parser::Token.new('c', c_)
27
+ Tokens::Token.new('a', a_),
28
+ Tokens::Token.new('a', a_),
29
+ Tokens::Token.new('b', b_),
30
+ Tokens::Token.new('c', c_),
31
+ Tokens::Token.new('c', c_)
32
32
  ]
33
33
  end
34
34
 
@@ -45,7 +45,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
45
45
  # +- c[4,5]
46
46
  # Capital letters represent non-terminal nodes
47
47
  let(:grm_abc_ptree1) do
48
- parser = Parser::EarleyParser.new(grammar_abc)
48
+ parser = Parser::GFGEarleyParser.new(grammar_abc)
49
49
  parse_result = parser.parse(grm_abc_tokens1)
50
50
  parse_result.parse_tree
51
51
  end
@@ -110,13 +110,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
110
110
 
111
111
  # Sample non-terminal node
112
112
  let(:nterm_node) do
113
- first_big_a = grm_abc_ptree1.root.children[0]
114
- second_big_a = first_big_a.children[1]
115
- second_big_a.children[1]
113
+ first_big_a = grm_abc_ptree1.root.subnodes[0]
114
+ second_big_a = first_big_a.subnodes[1]
115
+ second_big_a.subnodes[1]
116
116
  end
117
117
 
118
118
  # Sample terminal node
119
- let(:term_node) { nterm_node.children[0] }
119
+ let(:term_node) { nterm_node.subnodes[0] }
120
120
 
121
121
  it 'should react to the start_visit_ptree message' do
122
122
  # Notify subscribers when start the visit of the ptree
@@ -132,13 +132,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
132
132
 
133
133
  it 'should react to the visit_children message' do
134
134
  # Notify subscribers when start the visit of children nodes
135
- children = nterm_node.children
135
+ children = nterm_node.subnodes
136
136
  args = [nterm_node, children]
137
- expect(listener1).to receive(:before_children).with(*args)
137
+ expect(listener1).to receive(:before_subnodes).with(*args)
138
138
  expect(listener1).to receive(:before_terminal).with(children[0])
139
139
  expect(listener1).to receive(:after_terminal).with(children[0])
140
- expect(listener1).to receive(:after_children).with(nterm_node, children)
141
- subject.send(:traverse_children, nterm_node)
140
+ expect(listener1).to receive(:after_subnodes).with(nterm_node, children)
141
+ subject.send(:traverse_subnodes, nterm_node)
142
142
  end
143
143
 
144
144
  it 'should react to the end_visit_nonterminal message' do
@@ -172,37 +172,37 @@ module Rley # Open this namespace to avoid module qualifier prefixes
172
172
  # | +- c[3,4]
173
173
  # +- c[4,5]
174
174
  root = grm_abc_ptree1.root
175
- children = root.children
175
+ children = root.subnodes
176
176
  big_a_1 = children[0]
177
- big_a_1_children = big_a_1.children
177
+ big_a_1_children = big_a_1.subnodes
178
178
  big_a_2 = big_a_1_children[1]
179
- big_a_2_children = big_a_2.children
179
+ big_a_2_children = big_a_2.subnodes
180
180
  big_a_3 = big_a_2_children[1]
181
- big_a_3_children = big_a_3.children
181
+ big_a_3_children = big_a_3.subnodes
182
182
  expectations = [
183
183
  [:before_ptree, [grm_abc_ptree1]],
184
184
  [:before_non_terminal, [root]],
185
- [:before_children, [root, children]],
185
+ [:before_subnodes, [root, children]],
186
186
  [:before_non_terminal, [big_a_1]],
187
- [:before_children, [big_a_1, big_a_1_children]],
187
+ [:before_subnodes, [big_a_1, big_a_1_children]],
188
188
  [:before_terminal, [big_a_1_children[0]]],
189
189
  [:after_terminal, [big_a_1_children[0]]],
190
190
  [:before_non_terminal, [big_a_2]],
191
- [:before_children, [big_a_2, big_a_2_children]],
191
+ [:before_subnodes, [big_a_2, big_a_2_children]],
192
192
  [:before_terminal, [big_a_2_children[0]]],
193
193
  [:after_terminal, [big_a_2_children[0]]],
194
194
  [:before_non_terminal, [big_a_3]],
195
- [:before_children, [big_a_3, big_a_3_children]],
195
+ [:before_subnodes, [big_a_3, big_a_3_children]],
196
196
  [:before_terminal, [big_a_3_children[0]]],
197
197
  [:after_terminal, [big_a_3_children[0]]],
198
- [:after_children, [big_a_3, big_a_3_children]],
198
+ [:after_subnodes, [big_a_3, big_a_3_children]],
199
199
  [:before_terminal, [big_a_2_children[2]]],
200
200
  [:after_terminal, [big_a_2_children[2]]],
201
- [:after_children, [big_a_2, big_a_2_children]],
201
+ [:after_subnodes, [big_a_2, big_a_2_children]],
202
202
  [:before_terminal, [big_a_1_children[2]]],
203
203
  [:after_terminal, [big_a_1_children[2]]],
204
- [:after_children, [big_a_1, big_a_1_children]],
205
- [:after_children, [root, children]],
204
+ [:after_subnodes, [big_a_1, big_a_1_children]],
205
+ [:after_subnodes, [root, children]],
206
206
  [:after_ptree, [grm_abc_ptree1]]
207
207
  ]
208
208
  expectations.each do |(msg, args)|