rley 0.4.01 → 0.4.02

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/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)|