rley 0.1.08 → 0.1.09

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 (45) hide show
  1. checksums.yaml +8 -8
  2. data/.rubocop.yml +81 -74
  3. data/CHANGELOG.md +4 -0
  4. data/Rakefile +4 -6
  5. data/examples/grammars/grammar_L0.rb +31 -31
  6. data/examples/grammars/grammar_abc.rb +26 -26
  7. data/lib/rley/constants.rb +1 -1
  8. data/lib/rley/formatter/base_formatter.rb +1 -3
  9. data/lib/rley/formatter/debug.rb +1 -3
  10. data/lib/rley/formatter/json.rb +2 -5
  11. data/lib/rley/parse_tree_visitor.rb +0 -2
  12. data/lib/rley/parser/dotted_item.rb +3 -1
  13. data/lib/rley/parser/earley_parser.rb +4 -4
  14. data/lib/rley/parser/parsing.rb +10 -9
  15. data/lib/rley/parser/state_set.rb +1 -3
  16. data/lib/rley/ptree/non_terminal_node.rb +1 -1
  17. data/lib/rley/ptree/parse_tree.rb +32 -34
  18. data/lib/rley/ptree/parse_tree_node.rb +1 -3
  19. data/lib/rley/ptree/terminal_node.rb +1 -2
  20. data/lib/rley/ptree/token_range.rb +14 -14
  21. data/spec/rley/formatter/debug_spec.rb +65 -68
  22. data/spec/rley/formatter/json_spec.rb +69 -72
  23. data/spec/rley/parse_tree_visitor_spec.rb +5 -7
  24. data/spec/rley/parser/chart_spec.rb +0 -4
  25. data/spec/rley/parser/dotted_item_spec.rb +0 -3
  26. data/spec/rley/parser/earley_parser_spec.rb +0 -1
  27. data/spec/rley/parser/parse_state_spec.rb +0 -5
  28. data/spec/rley/parser/parsing_spec.rb +0 -3
  29. data/spec/rley/parser/state_set_spec.rb +0 -4
  30. data/spec/rley/parser/token_spec.rb +0 -4
  31. data/spec/rley/ptree/non_terminal_node_spec.rb +0 -1
  32. data/spec/rley/ptree/parse_tree_node_spec.rb +4 -4
  33. data/spec/rley/ptree/parse_tree_spec.rb +2 -3
  34. data/spec/rley/ptree/token_range_spec.rb +16 -17
  35. data/spec/rley/support/grammar_abc_helper.rb +0 -2
  36. data/spec/rley/syntax/grammar_builder_spec.rb +1 -4
  37. data/spec/rley/syntax/grammar_spec.rb +0 -9
  38. data/spec/rley/syntax/grm_symbol_spec.rb +0 -1
  39. data/spec/rley/syntax/literal_spec.rb +0 -1
  40. data/spec/rley/syntax/non_terminal_spec.rb +0 -1
  41. data/spec/rley/syntax/production_spec.rb +0 -2
  42. data/spec/rley/syntax/symbol_seq_spec.rb +0 -1
  43. data/spec/rley/syntax/terminal_spec.rb +0 -1
  44. data/spec/rley/syntax/verbatim_symbol_spec.rb +0 -1
  45. metadata +2 -2
@@ -45,7 +45,8 @@ module Rley # This module is used as a namespace
45
45
  if ptree.current_node.is_a?(PTree::TerminalNode)
46
46
  ptree.current_node.token = tokens[state_set_index]
47
47
  end
48
- parse_state = chart[state_set_index].predecessor_state(parse_state)
48
+ state_set = chart[state_set_index]
49
+ parse_state = state_set.predecessor_state(parse_state)
49
50
  curr_dotted_item = parse_state.dotted_rule
50
51
 
51
52
  when Syntax::NonTerminal
@@ -58,8 +59,8 @@ module Rley # This module is used as a namespace
58
59
  node_range = ptree.current_node.range
59
60
  ptree.add_children(curr_dotted_item.production, node_range)
60
61
  if ptree.current_node.is_a?(PTree::TerminalNode)
61
- curr_node = ptree.current_node
62
- curr_node.token = tokens[state_set_index-1] unless curr_node.token
62
+ a_node = ptree.current_node
63
+ a_node.token = tokens[state_set_index - 1] unless a_node.token
63
64
  end
64
65
 
65
66
  when NilClass
@@ -102,12 +103,12 @@ module Rley # This module is used as a namespace
102
103
  # determine the "next" dotted rule for a given one.
103
104
  def scanning(aTerminal, aPosition, &nextMapping)
104
105
  curr_token = tokens[aPosition]
105
- if curr_token.terminal == aTerminal
106
- states = states_expecting(aTerminal, aPosition)
107
- states.each do |s|
108
- next_item = nextMapping.call(s.dotted_rule)
109
- push_state(next_item, s.origin, aPosition + 1)
110
- end
106
+ return unless curr_token.terminal == aTerminal
107
+
108
+ states = states_expecting(aTerminal, aPosition)
109
+ states.each do |s|
110
+ next_item = nextMapping.call(s.dotted_rule)
111
+ push_state(next_item, s.origin, aPosition + 1)
111
112
  end
112
113
  end
113
114
 
@@ -42,15 +42,13 @@ module Rley # This module is used as a namespace
42
42
  # Retrieve the parse state that is the predecessor of the given one.
43
43
  def predecessor_state(aParseState)
44
44
  if aParseState.dotted_rule.prev_position.nil?
45
- raise StandardError, "#{aParseState}"
45
+ fail StandardError, "#{aParseState}"
46
46
  else
47
- prod = aParseState.dotted_rule.production
48
47
  candidate = states.find { |s| s.precedes?(aParseState) }
49
48
  end
50
49
 
51
50
  return candidate
52
51
  end
53
-
54
52
 
55
53
  private
56
54
 
@@ -26,4 +26,4 @@ module Rley # This module is used as a namespace
26
26
  end # class
27
27
  end # module
28
28
  end # module
29
- # End of file
29
+ # End of file
@@ -38,9 +38,9 @@ module Rley # This module is used as a namespace
38
38
  aProduction.rhs.each do |symb|
39
39
  case symb
40
40
  when Syntax::Terminal
41
- new_node = TerminalNode.new(symb,{})
41
+ new_node = TerminalNode.new(symb, {})
42
42
  when Syntax::NonTerminal
43
- new_node = NonTerminalNode.new(symb,{})
43
+ new_node = NonTerminalNode.new(symb, {})
44
44
  end
45
45
 
46
46
  current_node.add_child(new_node)
@@ -49,57 +49,55 @@ module Rley # This module is used as a namespace
49
49
  children = current_node.children
50
50
  children.first.range = low_bound(aRange)
51
51
  children.last.range = high_bound(aRange)
52
- unless children.empty?
53
- path_increment = [children.size - 1, children.last]
54
- @current_path.concat(path_increment)
55
- end
52
+ return if children.empty?
53
+
54
+ path_increment = [children.size - 1, children.last]
55
+ @current_path.concat(path_increment)
56
56
  end
57
-
57
+
58
58
  # Move the current node to the parent node.
59
59
  # @param tokenPos [Fixnum] position of the matching input token
60
- def step_up(tokenPos)
61
- (pos, last_node) = current_path.pop(2)
60
+ def step_up(_tokenPos)
61
+ current_path.pop(2)
62
62
  end
63
-
63
+
64
64
 
65
65
 
66
66
  # Move the current node to the previous sibling node.
67
67
  # @param tokenPos [Fixnum] position of the matching input token
68
68
  def step_back(tokenPos)
69
69
  (pos, last_node) = current_path[-2, 2]
70
- last_node.range = low_bound({low: tokenPos})
71
-
72
- if pos > 0
73
- current_path.pop(2)
74
- new_pos = pos - 1
75
- new_curr_node = current_path.last.children[new_pos]
76
- current_path << new_pos
77
- current_path << new_curr_node
78
- new_curr_node.range = high_bound({high: tokenPos})
79
- end
70
+ last_node.range = low_bound(low: tokenPos)
71
+
72
+ return if pos <= 0
73
+ current_path.pop(2)
74
+ new_pos = pos - 1
75
+ new_curr_node = current_path.last.children[new_pos]
76
+ current_path << new_pos
77
+ current_path << new_curr_node
78
+ new_curr_node.range = high_bound(high: tokenPos)
80
79
  end
81
80
 
82
81
  private
83
82
 
84
- def low_bound(aRange)
85
- result = case aRange
86
- when Hash then aRange[:low]
87
- when TokenRange then aRange.low
88
- end
89
-
90
- return { low: result }
83
+ def low_bound(aRange)
84
+ result = case aRange
85
+ when Hash then aRange[:low]
86
+ when TokenRange then aRange.low
91
87
  end
92
88
 
93
- def high_bound(aRange)
94
- result = case aRange
95
- when Hash then aRange[:high]
96
- when TokenRange then aRange.high
97
- end
89
+ return { low: result }
90
+ end
98
91
 
99
- return { high: result }
92
+ def high_bound(aRange)
93
+ result = case aRange
94
+ when Hash then aRange[:high]
95
+ when TokenRange then aRange.high
100
96
  end
101
97
 
98
+ return { high: result }
99
+ end
102
100
  end # class
103
101
  end # module
104
102
  end # module
105
- # End of file
103
+ # End of file
@@ -9,7 +9,6 @@ module Rley # This module is used as a namespace
9
9
  # A range of indices for tokens corresponding to the node.
10
10
  attr_reader(:range)
11
11
 
12
-
13
12
  def initialize(aSymbol, aRange)
14
13
  @symbol = aSymbol
15
14
  @range = TokenRange.new(aRange)
@@ -18,8 +17,7 @@ module Rley # This module is used as a namespace
18
17
  def range=(aRange)
19
18
  range.assign(aRange)
20
19
  end
21
-
22
20
  end # class
23
21
  end # module
24
22
  end # module
25
- # End of file
23
+ # End of file
@@ -15,8 +15,7 @@ module Rley # This module is used as a namespace
15
15
  def accept(aVisitor)
16
16
  aVisitor.visit_terminal(self)
17
17
  end
18
-
19
18
  end # class
20
19
  end # module
21
20
  end # module
22
- # End of file
21
+ # End of file
@@ -12,18 +12,18 @@ module Rley # This module is used as a namespace
12
12
  assign_low(aRangeRep)
13
13
  assign_high(aRangeRep)
14
14
  end
15
-
16
-
15
+
16
+
17
17
  def ==(other)
18
18
  return true if object_id == other.object_id
19
-
19
+
20
20
  case other
21
21
  when Hash
22
22
  result = low == other[:low] && high == other[:high]
23
23
  when TokenRange
24
24
  result = low == other.low && high == other.high
25
25
  end
26
-
26
+
27
27
  return result
28
28
  end
29
29
 
@@ -31,31 +31,31 @@ module Rley # This module is used as a namespace
31
31
  def bounded?()
32
32
  return !(low.nil? || high.nil?)
33
33
  end
34
-
34
+
35
35
  # Conditional assign
36
36
  def assign(aRange)
37
37
  return if bounded?
38
-
38
+
39
39
  assign_low(aRange) if low.nil?
40
40
  assign_high(aRange) if high.nil?
41
41
  end
42
-
42
+
43
43
  private
44
+
44
45
  def assign_low(aRange)
45
46
  case aRange
46
- when Hash then @low = aRange.fetch(:low, nil)
47
- when TokenRange then @low = aRange.low
47
+ when Hash then @low = aRange.fetch(:low, nil)
48
+ when TokenRange then @low = aRange.low
48
49
  end
49
50
  end
50
-
51
+
51
52
  def assign_high(aRange)
52
53
  case aRange
53
- when Hash then @high = aRange.fetch(:high, nil)
54
- when TokenRange then @high = aRange.high
54
+ when Hash then @high = aRange.fetch(:high, nil)
55
+ when TokenRange then @high = aRange.high
55
56
  end
56
57
  end
57
-
58
58
  end # class
59
59
  end # module
60
60
  end # module
61
- # End of file
61
+ # End of file
@@ -10,75 +10,73 @@ require_relative '../../../lib/rley/parse_tree_visitor'
10
10
  require_relative '../../../lib/rley/formatter/debug'
11
11
 
12
12
  module Rley # Re-open the module to get rid of qualified names
13
- module Formatter
13
+ module Formatter
14
+ describe Debug do
15
+ include GrammarABCHelper # Mix-in module for grammar abc
14
16
 
15
- describe Debug do
16
- include GrammarABCHelper # Mix-in module with builder for grammar abc
17
+ # Factory method. Build a production with the given sequence
18
+ # of symbols as its rhs.
19
+ let(:grammar_abc) do
20
+ builder = grammar_abc_builder
21
+ builder.grammar
22
+ end
23
+
24
+ # Variables for the terminal symbols
25
+ let(:a_) { grammar_abc.name2symbol['a'] }
26
+ let(:b_) { grammar_abc.name2symbol['b'] }
27
+ let(:c_) { grammar_abc.name2symbol['c'] }
28
+
29
+ # Helper method that mimicks the output of a tokenizer
30
+ # for the language specified by gramma_abc
31
+ let(:grm_abc_tokens1) do
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_)
38
+ ]
39
+ end
17
40
 
18
- # Factory method. Build a production with the given sequence
19
- # of symbols as its rhs.
20
- let(:grammar_abc) do
21
- builder = grammar_abc_builder
22
- builder.grammar
23
- end
24
-
25
- # Variables for the terminal symbols
26
- let(:a_) { grammar_abc.name2symbol['a'] }
27
- let(:b_) { grammar_abc.name2symbol['b'] }
28
- let(:c_) { grammar_abc.name2symbol['c'] }
29
-
30
- # Helper method that mimicks the output of a tokenizer
31
- # for the language specified by gramma_abc
32
- let(:grm_abc_tokens1) do
33
- [
34
- Parser::Token.new('a', a_),
35
- Parser::Token.new('a', a_),
36
- Parser::Token.new('b', b_),
37
- Parser::Token.new('c', c_),
38
- Parser::Token.new('c', c_)
39
- ]
40
- end
41
-
42
- # Factory method that builds a sample parse tree.
43
- # Generated tree has the following structure:
44
- # S[0,5]
45
- # +- A[0,5]
46
- # +- a[0,0]
47
- # +- A[1,4]
48
- # | +- a[1,1]
49
- # | +- A[2,3]
50
- # | | +- b[2,3]
51
- # | +- c[3,4]
52
- # +- c[4,5]
53
- # Capital letters represent non-terminal nodes
54
- let(:grm_abc_ptree1) do
55
- parser = Parser::EarleyParser.new(grammar_abc)
56
- parse_result = parser.parse(grm_abc_tokens1)
57
- parse_result.parse_tree
58
- end
41
+ # Factory method that builds a sample parse tree.
42
+ # Generated tree has the following structure:
43
+ # S[0,5]
44
+ # +- A[0,5]
45
+ # +- a[0,0]
46
+ # +- A[1,4]
47
+ # | +- a[1,1]
48
+ # | +- A[2,3]
49
+ # | | +- b[2,3]
50
+ # | +- c[3,4]
51
+ # +- c[4,5]
52
+ # Capital letters represent non-terminal nodes
53
+ let(:grm_abc_ptree1) do
54
+ parser = Parser::EarleyParser.new(grammar_abc)
55
+ parse_result = parser.parse(grm_abc_tokens1)
56
+ parse_result.parse_tree
57
+ end
59
58
 
60
- let(:destination) { StringIO.new('', 'w') }
61
-
62
- context 'Standard creation & initialization:' do
59
+ let(:destination) { StringIO.new('', 'w') }
63
60
 
64
- it 'should be initialized with an IO argument' do
65
- expect { Debug.new(StringIO.new('', 'w')) }.not_to raise_error
66
- end
67
-
68
- it 'should know its output destination' do
69
- instance = Debug.new(destination)
70
- expect(instance.output).to eq(destination)
71
- end
72
- end # context
61
+ context 'Standard creation & initialization:' do
62
+ it 'should be initialized with an IO argument' do
63
+ expect { Debug.new(StringIO.new('', 'w')) }.not_to raise_error
64
+ end
65
+
66
+ it 'should know its output destination' do
67
+ instance = Debug.new(destination)
68
+ expect(instance.output).to eq(destination)
69
+ end
70
+ end # context
73
71
 
74
72
 
75
73
 
76
- context 'Formatting events:' do
77
- it 'should support visit events of a parse tree' do
78
- instance = Debug.new(destination)
79
- visitor = Rley::ParseTreeVisitor.new(grm_abc_ptree1)
80
- instance.render(visitor)
81
- expectations = <<-SNIPPET
74
+ context 'Formatting events:' do
75
+ it 'should support visit events of a parse tree' do
76
+ instance = Debug.new(destination)
77
+ visitor = Rley::ParseTreeVisitor.new(grm_abc_ptree1)
78
+ instance.render(visitor)
79
+ expectations = <<-SNIPPET
82
80
  before_ptree
83
81
  before_non_terminal
84
82
  before_children
@@ -108,12 +106,11 @@ before_ptree
108
106
  after_non_terminal
109
107
  after_ptree
110
108
  SNIPPET
111
- expect(destination.string).to eq(expectations)
112
- end
113
- end # context
114
- end # describe
115
-
116
- end # module
109
+ expect(destination.string).to eq(expectations)
110
+ end
111
+ end # context
112
+ end # describe
113
+ end # module
117
114
  end # module
118
115
 
119
116
  # End of file
@@ -11,75 +11,73 @@ require_relative '../../../lib/rley/parse_tree_visitor'
11
11
  require_relative '../../../lib/rley/formatter/json'
12
12
 
13
13
  module Rley # Re-open the module to get rid of qualified names
14
- module Formatter
14
+ module Formatter
15
+ describe Json do
16
+ include GrammarABCHelper # Mix-in module with builder for grammar abc
15
17
 
16
- describe Json do
17
- include GrammarABCHelper # Mix-in module with builder for grammar abc
18
-
19
- # Factory method. Build a production with the given sequence
20
- # of symbols as its rhs.
21
- let(:grammar_abc) do
22
- builder = grammar_abc_builder
23
- builder.grammar
24
- end
25
-
26
- # Variables for the terminal symbols
27
- let(:a_) { grammar_abc.name2symbol['a'] }
28
- let(:b_) { grammar_abc.name2symbol['b'] }
29
- let(:c_) { grammar_abc.name2symbol['c'] }
30
-
31
- # Helper method that mimicks the output of a tokenizer
32
- # for the language specified by gramma_abc
33
- let(:grm_abc_tokens1) do
34
- [
35
- Parser::Token.new('a', a_),
36
- Parser::Token.new('a', a_),
37
- Parser::Token.new('b', b_),
38
- Parser::Token.new('c', c_),
39
- Parser::Token.new('c', c_)
40
- ]
41
- end
42
-
43
- # Factory method that builds a sample parse tree.
44
- # Generated tree has the following structure:
45
- # S[0,5]
46
- # +- A[0,5]
47
- # +- a[0,0]
48
- # +- A[1,4]
49
- # | +- a[1,1]
50
- # | +- A[2,3]
51
- # | | +- b[2,3]
52
- # | +- c[3,4]
53
- # +- c[4,5]
54
- # Capital letters represent non-terminal nodes
55
- let(:grm_abc_ptree1) do
56
- parser = Parser::EarleyParser.new(grammar_abc)
57
- parse_result = parser.parse(grm_abc_tokens1)
58
- parse_result.parse_tree
59
- end
60
-
61
- let(:destination) { StringIO.new('', 'w') }
18
+ # Factory method. Build a production with the given sequence
19
+ # of symbols as its rhs.
20
+ let(:grammar_abc) do
21
+ builder = grammar_abc_builder
22
+ builder.grammar
23
+ end
24
+
25
+ # Variables for the terminal symbols
26
+ let(:a_) { grammar_abc.name2symbol['a'] }
27
+ let(:b_) { grammar_abc.name2symbol['b'] }
28
+ let(:c_) { grammar_abc.name2symbol['c'] }
29
+
30
+ # Helper method that mimicks the output of a tokenizer
31
+ # for the language specified by gramma_abc
32
+ let(:grm_abc_tokens1) do
33
+ [
34
+ Parser::Token.new('a', a_),
35
+ Parser::Token.new('a', a_),
36
+ Parser::Token.new('b', b_),
37
+ Parser::Token.new('c', c_),
38
+ Parser::Token.new('c', c_)
39
+ ]
40
+ end
62
41
 
63
- context 'Standard creation & initialization:' do
42
+ # Factory method that builds a sample parse tree.
43
+ # Generated tree has the following structure:
44
+ # S[0,5]
45
+ # +- A[0,5]
46
+ # +- a[0,0]
47
+ # +- A[1,4]
48
+ # | +- a[1,1]
49
+ # | +- A[2,3]
50
+ # | | +- b[2,3]
51
+ # | +- c[3,4]
52
+ # +- c[4,5]
53
+ # Capital letters represent non-terminal nodes
54
+ let(:grm_abc_ptree1) do
55
+ parser = Parser::EarleyParser.new(grammar_abc)
56
+ parse_result = parser.parse(grm_abc_tokens1)
57
+ parse_result.parse_tree
58
+ end
59
+
60
+ let(:destination) { StringIO.new('', 'w') }
64
61
 
65
- it 'should be initialized with an IO argument' do
66
- expect { Json.new(StringIO.new('', 'w')) }.not_to raise_error
67
- end
68
-
69
- it 'should know its output destination' do
70
- instance = Json.new(destination)
71
- expect(instance.output).to eq(destination)
72
- end
73
- end # context
74
-
62
+ context 'Standard creation & initialization:' do
63
+ it 'should be initialized with an IO argument' do
64
+ expect { Json.new(StringIO.new('', 'w')) }.not_to raise_error
65
+ end
66
+
67
+ it 'should know its output destination' do
68
+ instance = Json.new(destination)
69
+ expect(instance.output).to eq(destination)
70
+ end
71
+ end # context
72
+
75
73
 
76
-
77
- context 'Formatting events:' do
78
- it 'should render a parse tree in JSON' do
79
- instance = Json.new(destination)
80
- visitor = Rley::ParseTreeVisitor.new(grm_abc_ptree1)
81
- instance.render(visitor)
82
- expectations = <<-SNIPPET
74
+
75
+ context 'Formatting events:' do
76
+ it 'should render a parse tree in JSON' do
77
+ instance = Json.new(destination)
78
+ visitor = Rley::ParseTreeVisitor.new(grm_abc_ptree1)
79
+ instance.render(visitor)
80
+ expectations = <<-SNIPPET
83
81
  {
84
82
  "root":
85
83
  { "S": [
@@ -100,13 +98,12 @@ describe Json do
100
98
  ]
101
99
  }
102
100
  }
103
- SNIPPET
104
- expect(destination.string).to eq(expectations.chomp)
105
- end
106
- end # context
107
- end # describe
108
-
109
- end # module
101
+ SNIPPET
102
+ expect(destination.string).to eq(expectations.chomp)
103
+ end
104
+ end # context
105
+ end # describe
106
+ end # module
110
107
  end # module
111
108
 
112
109
  # End of file