dendroid 0.2.02 → 0.2.03

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb58d7b275f7eb65ccfef37ee213fc53319c5634cf8dbd79020451c79769a3c3
4
- data.tar.gz: f075b751545df13bda67d3e2df1c3861dfdaffa8fc416a7a735d0c4fc2da01bb
3
+ metadata.gz: ba78964528c386b4be6024fdd2f1f76edc87478e83013ac40933d183e0d04d02
4
+ data.tar.gz: 1a5840b2d92a8b8e525bdf1313122ae3f3160fbb9676700c8e4d3edede71928b
5
5
  SHA512:
6
- metadata.gz: 1f3598bbc4f19ff183e655a92ca86908615a10b2f142982c09eb11b01b9fd05296db1ce5b9fa14be9d5f71c8358fd60535a0eb8b0feea8fcddafae5100fe8df4
7
- data.tar.gz: c3227a5e8cb2675d2de6d011091e3b665e0217e62401619db36e43967a9d407c06a50205031c03dacc43f72b01cd1b0ebf66132240194d61de1ae1e167594113
6
+ metadata.gz: 241163fd9a9f7ab036a1d750ef30844f538b40e2fea401af86929798a98f515ec9a82d136f2db7e61c3253ce7c88e9166db55ef24373a47acc0a6dd043e84c61
7
+ data.tar.gz: ee0faca7992fa087ca100b0de21b7e85464828a832462cded6593688d20b6b834a11d87284f7a3fcce137dbc670db98499e5601587119e32d25f5ab2f61a4134
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.2.03] - 2023-12-21
6
+
7
+ ### Added
8
+ - YARD documentation for the `ParseNode` hierarchy.
9
+ - Classes `Token` and `Literal` added the predicate method `literal?`
10
+
11
+ ### Changed
12
+ - Class rename: `ANDNode` became `AndNode`
13
+ - Class `ParseNode`: method rename: `ParseNode#to_s` became `ParseNode#range_to_s`
14
+ - Class `ParseNode`: attribute `range` is now of type `Range`
15
+
5
16
  ## [0.2.02] - 2023-12-18
6
17
  Code re-styling to fix most Rubocop offenses.
7
18
 
@@ -6,7 +6,7 @@ class BracketNotation < BaseFormatter
6
6
  # Method called by a ParseTreeVisitor to which the formatter subscribed.
7
7
  # Notification of a visit event: the visitor is about to visit
8
8
  # a non-terminal node
9
- # @param and_node [ANDNode]
9
+ # @param and_node [AndNode]
10
10
  def before_and_node(and_node)
11
11
  write("[#{and_node.rule.lhs.name} ")
12
12
  end
@@ -21,7 +21,7 @@ module Dendroid
21
21
  # An item with the dot not at the beginning is sometimes referred to as a kernel item
22
22
  class DottedItem
23
23
  # (Weak) reference to the production rule
24
- # @return [Dendroid::Syntax::Production]
24
+ # @return [Dendroid::Syntax::Rule]
25
25
  attr_reader :rule
26
26
 
27
27
  # @return [Integer] the dot position
@@ -31,12 +31,12 @@ module Dendroid
31
31
  attr_reader :alt_index
32
32
 
33
33
  # Constructor.
34
- # @param aChoice [Dendroid::Syntax::Rule]
34
+ # @param aRule[Dendroid::Syntax::Rule]
35
35
  # @param aPosition [Integer] Position of the dot in rhs of production.
36
36
  # @param index [Integer] the rank of the alternative at hand
37
- def initialize(aChoice, aPosition, index)
37
+ def initialize(aRule, aPosition, index)
38
38
  @alt_index = index
39
- @rule = WeakRef.new(aChoice)
39
+ @rule = WeakRef.new(aRule)
40
40
  @position = valid_position(aPosition)
41
41
  end
42
42
 
@@ -23,6 +23,11 @@ module Dendroid
23
23
  super(original, pos, symbol)
24
24
  @value = aValue
25
25
  end
26
+
27
+ # @return [Boolean] true if the token is a literal (has a value associated with is)
28
+ def literal?
29
+ true
30
+ end
26
31
  end # class
27
32
  end # module
28
33
  end # module
@@ -41,6 +41,11 @@ module Dendroid
41
41
  def pos_to_s
42
42
  position.to_s
43
43
  end
44
+
45
+ # @return [Boolean] true if the token is a literal (has a value associated with is)
46
+ def literal?
47
+ false
48
+ end
44
49
  end # class
45
50
  end # module
46
51
  end # module
@@ -4,10 +4,18 @@ require_relative 'composite_parse_node'
4
4
 
5
5
  module Dendroid
6
6
  module Parsing
7
- class ANDNode < CompositeParseNode
7
+ # A composite parse node that matches the sequence of grammar symbols from
8
+ # a right-hand side of a rule to a range of input tokens. The child nodes
9
+ # correspond to the grammar symbols in the RHS of the rule.
10
+ class AndNode < CompositeParseNode
11
+ # @return [WeakRef<Dendroid::Syntax::Rule>] Grammar rule
8
12
  attr_reader :rule
13
+
14
+ # @return [Integer] Index of the rule alternative.
9
15
  attr_reader :alt_index
10
16
 
17
+ # @param anEItem [Dendroid::Recognizer::EItem] An entry from the chart.
18
+ # @param rank [Integer] rank of the last input token matched by this node
11
19
  def initialize(anEItem, rank)
12
20
  @rule = WeakRef.new(anEItem.dotted_item.rule)
13
21
  @alt_index = anEItem.dotted_item.alt_index
@@ -15,14 +23,22 @@ module Dendroid
15
23
  super(anEItem.origin, upper_bound, rule.rhs[alt_index].size)
16
24
  end
17
25
 
26
+ # Add a child a given available position.
27
+ # @param child_node [Dendroid::Parsing::ParseNode] Node to add as a child
28
+ # @param index [Integer] position of the child node in the `children` array
18
29
  def add_child(child_node, index)
19
30
  raise StandardError unless children[index].nil? # Is slot available?
20
31
 
21
32
  super(child_node, index)
22
33
  end
23
34
 
35
+ # Is the given chart entry matching this node?
36
+ # The chart entry matches this node if:
37
+ # - its origin equals to the start of the range; and,
38
+ # - both rules are the same; and,
39
+ # @return [Boolean] true if the entry corresponds to this node.
24
40
  def match(anEItem)
25
- return false if range[0] != anEItem.origin
41
+ return false if range.begin != anEItem.origin
26
42
 
27
43
  dotted = anEItem.dotted_item
28
44
  same_rule = (rule.lhs == dotted.rule.lhs) && (alt_index == dotted.alt_index)
@@ -31,17 +47,23 @@ module Dendroid
31
47
  dotted.initial_pos? ? true : partial?
32
48
  end
33
49
 
50
+ # Is this node expecting at given RHS index, the given symbol?
51
+ # @param symbol [Dendroid::Syntax::GrmSymbol]
52
+ # @param position [Integer] index of given member in RHS of the rule
34
53
  def expecting?(symbol, position)
35
54
  symb_seq = rule.rhs[alt_index]
36
55
  symb_seq[position] == symbol
37
56
  end
38
57
 
58
+ # @return [Boolean] true if at least one of the children slots is free.
39
59
  def partial?
40
60
  children.any?(&:nil?)
41
61
  end
42
62
 
63
+ # Return a String representation of itself
64
+ # @return [String] text representation of itself
43
65
  def to_s
44
- "#{rule.lhs} => #{rule.rhs[alt_index]} #{range}"
66
+ "#{rule.lhs} => #{rule.rhs[alt_index]} #{range_to_s}"
45
67
  end
46
68
 
47
69
  # Part of the 'visitee' role in Visitor design pattern.
@@ -27,11 +27,11 @@ module Dendroid
27
27
  # Create n times start_item as predecessors, then for each path initialize to its unique own predecessor
28
28
  forerunners = disambiguate(progress, start_item.predecessors)
29
29
  if forerunners.size == 1
30
- parents << ANDNode.new(start_item, curr_rank)
30
+ parents << AndNode.new(start_item, curr_rank)
31
31
  else
32
32
  preds = sort_predecessors(forerunners)
33
33
  if start_item.rule.rhs.size == 1
34
- parents << ANDNode.new(start_item, curr_rank)
34
+ parents << AndNode.new(start_item, curr_rank)
35
35
  progress.push_or_node(start_item.origin, preds.size)
36
36
  else
37
37
  parents << OrNode.new(start_item.lhs, start_item.origin, curr_rank, preds.size)
@@ -40,7 +40,7 @@ module Dendroid
40
40
  fork(progress, paths, preds)
41
41
  end
42
42
  else
43
- parents << ANDNode.new(start_item, curr_rank)
43
+ parents << AndNode.new(start_item, curr_rank)
44
44
  end
45
45
  token2node = {}
46
46
  entry2node = {}
@@ -4,9 +4,14 @@ require_relative 'parse_node'
4
4
 
5
5
  module Dendroid
6
6
  module Parsing
7
+ # Composite Pattern. A specialization of parse nodes that have themselves children nodes.
7
8
  class CompositeParseNode < ParseNode
9
+ # @return [Array<Dendroid::Parsing::ParseNode|NilClass>] Sub-nodes. Nil values represent available slots
8
10
  attr_reader :children
9
11
 
12
+ # @param lowerBound [Integer] Rank of first input token that is matched by this node
13
+ # @param upperBound [Integer] Rank of last input token that is matched by this node
14
+ # @param child_count [Integer] The expected number of child nodes
10
15
  def initialize(lowerBound, upperBound, child_count)
11
16
  super(lowerBound, upperBound)
12
17
  @children = Array.new(child_count, nil)
@@ -1,21 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'weakref'
3
4
  require_relative 'parse_node'
4
5
 
5
6
  module Dendroid
6
7
  module Parsing
8
+ # A parse tree/forest node that is related to a production rule with an empty
9
+ # RHS (right-hand side).
7
10
  class EmptyRuleNode < ParseNode
11
+ # @return [WeakRef<Dendroid::Syntax::Rule>] Grammar rule
8
12
  attr_reader :rule
13
+
14
+ # @return [Integer] Index of the rule alternative.
9
15
  attr_reader :alt_index
10
16
 
17
+ # @param anEItem [Dendroid::Recognizer::EItem] An entry from the chart.
18
+ # @param rank [Integer] rank of the last input token matched by this node
11
19
  def initialize(anEItem, rank)
12
20
  super(rank, rank)
13
21
  @rule = WeakRef.new(anEItem.dotted_item.rule)
14
22
  @alt_index = anEItem.dotted_item.alt_index
15
23
  end
16
24
 
25
+ # Return a String representation of itself
26
+ # @return [String] text representation of itself
17
27
  def to_s
18
- "_ #{super}"
28
+ "_ #{range_to_s}"
19
29
  end
20
30
 
21
31
  # Part of the 'visitee' role in Visitor design pattern.
@@ -4,14 +4,25 @@ require_relative 'composite_parse_node'
4
4
 
5
5
  module Dendroid
6
6
  module Parsing
7
+ # A composite parse node that embodies multiple syntactical derivations of a right-hand side of a rule
8
+ # to a range of input tokens. Each child node corresponds to a distinct derivation.
7
9
  class OrNode < CompositeParseNode
10
+ # @return [Dendroid::Syntax::NonTerminal] The non-terminal symbol at LHS of rule
8
11
  attr_reader :symbol
9
12
 
13
+ # @param sym [Dendroid::Syntax::NonTerminal]
14
+ # @param lower [Integer] lowest token rank matching start of the rule
15
+ # @param upper [Integer] largest token rank matching start of the rule
16
+ # @param arity [Integer] Number of derivations of the given rule
10
17
  def initialize(sym, lower, upper, arity)
11
18
  @symbol = sym
12
19
  super(lower, upper, arity)
13
20
  end
14
21
 
22
+ # Add a child node as root of one derivation.
23
+ # Place it in an available child slot.
24
+ # @param child_node [Dendroid::Parsing::ParseNode]
25
+ # @param _index [Integer] Unused
15
26
  def add_child(child_node, _index)
16
27
  idx = children.find_index(&:nil?)
17
28
  raise StandardError unless idx
@@ -20,20 +31,29 @@ module Dendroid
20
31
  super(child_node, idx)
21
32
  end
22
33
 
34
+ # Is the given chart entry matching this node?
35
+ # The chart entry matches this node if:
36
+ # - its origin equals to the start of the range; and,
37
+ # - both rules are the same; and,
38
+ # - each child matches this chart entry
39
+ # @return [Boolean] true if the entry corresponds to this node.
23
40
  def match(anEItem)
24
- return false if range[0] != anEItem.origin
41
+ return false if range.begin != anEItem.origin
25
42
 
26
43
  dotted = anEItem.dotted_item
27
44
  (symbol == dotted.rule.lhs) && children.any? { |ch| ch.match(anEItem) }
28
45
  end
29
46
 
47
+ # @return [FalseClass]
30
48
  def partial?
31
49
  # children.any?(&:nil?)
32
50
  false
33
51
  end
34
52
 
53
+ # Return a String representation of itself
54
+ # @return [String] text representation of itself
35
55
  def to_s
36
- "OR: #{symbol.name} #{range}"
56
+ "OR: #{symbol.name} #{range_to_s}"
37
57
  end
38
58
 
39
59
  # Part of the 'visitee' role in Visitor design pattern.
@@ -1,17 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dendroid
4
+ # Namespace for all classes needed for implementing a generic parser.
5
+ # The goal is to take the output from the Earley recognizer (i.e. a chart object),
6
+ # visit it and build a data structure (a parse tree or a shared parse forest) that is much
7
+ # more convenient for subsequent processing (e.g. semantic analysis of a compiler/interpreter).
4
8
  module Parsing
9
+ # An abstract class (i.e. a generalization) for elements forming a parse tree (forest).
10
+ # A parse tree is a graph data structure that represents the parsed input text into a tree-like hierarchy
11
+ # of elements constructed by applying syntax rules of the language at hand.
12
+ # A parse forest is a data structure that merges a number parse trees into one graph.
13
+ # Contrary to parse trees, a parse forests can represent the results of an ambiguous parsing.
5
14
  class ParseNode
6
- # @return [Array<Integer>] The range of input tokens that match this node.
15
+ # @return [Range] The range of indexes of the input tokens that match this node.
7
16
  attr_reader :range
8
17
 
18
+ # @param lowerBound [Integer] Rank of first input token that is matched by this node
19
+ # @param upperBound [Integer] Rank of last input token that is matched by this node
9
20
  def initialize(lowerBound, upperBound)
10
21
  @range = valid_range(lowerBound, upperBound)
11
22
  end
12
23
 
13
- def to_s
14
- "[#{range[0]}, #{range[1]}]"
24
+ protected
25
+
26
+ def range_to_s
27
+ "[#{range}]"
15
28
  end
16
29
 
17
30
  private
@@ -19,7 +32,7 @@ module Dendroid
19
32
  def valid_range(lowerBound, upperBound)
20
33
  raise StandardError unless lowerBound.is_a?(Integer) && upperBound.is_a?(Integer)
21
34
 
22
- [lowerBound, upperBound]
35
+ lowerBound..upperBound
23
36
  end
24
37
  end # class
25
38
  end # module
@@ -45,7 +45,7 @@ class ParseTreeVisitor
45
45
  end
46
46
 
47
47
  # Visit event. The visitor is about to visit the given non terminal node.
48
- # @param aNonTerminalNode [ANDNode] the node to visit.
48
+ # @param aNonTerminalNode [AndNode] the node to visit.
49
49
  def visit_and_node(aNonTerminalNode)
50
50
  if @traversal == :post_order
51
51
  broadcast(:before_and_node, aNonTerminalNode)
@@ -4,6 +4,7 @@ require_relative 'parse_node'
4
4
 
5
5
  module Dendroid
6
6
  module Parsing
7
+ # A parse tree/forest node that is related to one input token.
7
8
  class TerminalNode < ParseNode
8
9
  # @return [Dendroid::Syntax::Terminal] Terminal symbol of matching token.
9
10
  attr_reader :symbol
@@ -23,9 +24,11 @@ module Dendroid
23
24
  aVisitor.visit_terminal(self)
24
25
  end
25
26
 
27
+ # Render a String representation of itself
28
+ # @return [String]
26
29
  def to_s
27
- display_val = token.is_a?(Dendroid::Lexical::Literal) ? ": #{token.value}" : ''
28
- "#{symbol.name}#{display_val} #{super}"
30
+ display_val = token.literal? ? ": #{token.value}" : ''
31
+ "#{symbol.name}#{display_val} #{range_to_s}"
29
32
  end
30
33
  end # class
31
34
  end # module
@@ -1,22 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'and_node'
3
+ require_relative 'and_node.rb'
4
4
  require_relative 'or_node'
5
5
  require_relative 'terminal_node'
6
6
  require_relative 'empty_rule_node'
7
7
 
8
8
  module Dendroid
9
9
  module Parsing
10
+ # This object holds the current state of the visit of a Chart by one
11
+ # ChartWalker through one single visit path. A path corresponds to a
12
+ # chain from the current item back to the initial item(s) through the predecessors links.
13
+ # It is used to construct (part of) the parse tree from the root node.
10
14
  class WalkProgress
15
+ # @return [Symbol] One of: :New, :Forking,
11
16
  attr_accessor :state
17
+
18
+ # @return [Integer] rank of the item set from the chart being visited
12
19
  attr_accessor :curr_rank
20
+
21
+ # @return [Dendroid::Recognizer::EItem] the chart entry being visited
13
22
  attr_reader :curr_item
23
+
24
+ # When not nil, override the predecessors links of the current item
25
+ # @return [Dendroid::Recognizer::EItem|NilClass]
14
26
  attr_accessor :predecessor
27
+
28
+ # @return [Array<Dendroid::Parsing::CompositeParseNode>] The ancestry of current parse node.
15
29
  attr_reader :parents
16
30
 
17
31
  # rubocop: disable Metrics/CyclomaticComplexity
18
32
  # rubocop: disable Metrics/PerceivedComplexity
19
33
 
34
+ # @param start_rank [Integer] Initial rank at the start of the visit
35
+ # @param start_item [Dendroid::Recognizer::EItem] Initial chart entry to visit
36
+ # @param parents [Array<Dendroid::Parsing::CompositeParseNode>]
20
37
  def initialize(start_rank, start_item, parents)
21
38
  @state = :New
22
39
  @curr_rank = start_rank
@@ -34,32 +51,46 @@ module Dendroid
34
51
  @parents = orig.parents.dup
35
52
  end
36
53
 
54
+ # Current item has multiple predecessors: set the state to Forking and
55
+ # force one of the predecessor to be the next entry to visit.
56
+ # @param thePredecessor [Dendroid::Recognizer::EItem]
37
57
  def fork(thePredecessor)
38
58
  @state = :Forking
39
59
  @predecessor = thePredecessor
40
60
  end
41
61
 
62
+ # Set the current entry being visited to the given one
63
+ # @param anEntry [Dendroid::Recognizer::EItem]
42
64
  def curr_item=(anEntry)
43
65
  raise StandardError if anEntry.nil?
44
66
 
45
67
  @curr_item = anEntry
46
68
  end
47
69
 
70
+ # Add a child leaf node for the given chart entry that corresponds
71
+ # to an empty rule.
72
+ # @param anEntry [Dendroid::Recognizer::EItem]
73
+ # @return [Dendroid::Parsing::EmptyRuleNode]
48
74
  def add_node_empty(anEntry)
49
75
  node_empty = EmptyRuleNode.new(anEntry, curr_rank)
50
76
  add_child_node(node_empty)
51
77
  end
52
78
 
53
- # Add a terminal node for terminal at current rank as a child of last parent
79
+ # Add a leaf terminal node for the token at current rank as a child of last parent.
80
+ # @param token [Dendroid::Lexical::Token]
81
+ # @return [Dendroid::Parsing::TerminalNode]
54
82
  def add_terminal_node(token)
55
83
  @curr_rank -= 1
56
84
  term_node = TerminalNode.new(curr_item.prev_symbol, token, curr_rank)
57
85
  add_child_node(term_node)
58
86
  end
59
87
 
60
- # Add an AND node for given entry as a child of last parent
88
+ # Make an AND node for the given entry as a child of last parent and
89
+ # push this node in the ancestry
90
+ # @param anEntry [Dendroid::Recognizer::EItem]
91
+ # @return [Dendroid::Parsing::AndNode]
61
92
  def push_and_node(anEntry)
62
- node = ANDNode.new(anEntry, curr_rank)
93
+ node = AndNode.new(anEntry, curr_rank)
63
94
  raise StandardError unless anEntry.rule == node.rule # Fails
64
95
 
65
96
  add_child_node(node)
@@ -68,6 +99,11 @@ module Dendroid
68
99
  node
69
100
  end
70
101
 
102
+ # Make an OR node as a child of last parent and
103
+ # push this node in the ancestry.
104
+ # @param origin [Integer] Start rank
105
+ # #param arity [Integer] The number of alternative derivations
106
+ # @return [Dendroid::Parsing::OrNode]
71
107
  def push_or_node(origin, arity)
72
108
  node = OrNode.new(curr_item.prev_symbol, origin, curr_rank, arity)
73
109
  add_child_node(node)
@@ -76,6 +112,9 @@ module Dendroid
76
112
  node
77
113
  end
78
114
 
115
+ # Add the given node as a child of the last parent node.
116
+ # @param aNode [Dendroid::Parsing::ParseNode]
117
+ # @return [Dendroid::Parsing::ParseNode]
79
118
  def add_child_node(aNode)
80
119
  parents.last.add_child(aNode, curr_item.position - 1)
81
120
  aNode
@@ -83,6 +122,8 @@ module Dendroid
83
122
 
84
123
  # Do the given EItems match one of the parent?
85
124
  # Matching = corresponds to the same rule and range
125
+ # @param entries [Dendroid::Recognizer::EItem]
126
+ # @param stop_at_first [Boolean] Must be true
86
127
  # @return [Array<EItem>]
87
128
  def match_parent?(entries, stop_at_first)
88
129
  matching = []
@@ -106,7 +147,7 @@ module Dendroid
106
147
  break if stop_at_first && !matching.empty?
107
148
 
108
149
  # Stop loop when parent.origin < min(entries.origin)
109
- break if node.range[0] < min_origin
150
+ break if node.range.begin < min_origin
110
151
 
111
152
  offset += 1
112
153
  end
@@ -8,6 +8,7 @@ module Dendroid
8
8
  # An Earley item is essentially a pair consisting of a dotted item and the rank of a token.
9
9
  # It helps to keep track the progress of an Earley recognizer.
10
10
  class EItem
11
+ # Mix-in module used to forward some method calls to the related dotted item.
11
12
  extend Forwardable
12
13
 
13
14
  # (Weak) reference to the dotted item
@@ -17,7 +18,8 @@ module Dendroid
17
18
  # @return [Integer] the rank of the token that correspond to the start of the rule.
18
19
  attr_reader :origin
19
20
 
20
- # TODO: :predictor, :completer, :scanner
21
+ # Specifies the algorithm with which this entry can be derived from its predecessor(s).
22
+ # @return [Symbol] of one: :predictor, :completer, :scanner
21
23
  attr_accessor :algo
22
24
 
23
25
  # @return [Array<WeakRef>] predecessors sorted by decreasing origin value
@@ -12,7 +12,7 @@ module Dendroid
12
12
  # @return [Array<Dendroid::Syntax::SymbolSeq>]
13
13
  attr_reader :alternatives
14
14
 
15
- # Create a Choice instance.
15
+ # Create a Rule instance.
16
16
  # @param theLhs [Dendroid::Syntax::NonTerminal] The left-hand side of the rule.
17
17
  # @param alt [Array<Dendroid::Syntax::SymbolSeq>] the alternatives (each as a sequence of symbols).
18
18
  def initialize(theLhs, alt)
@@ -16,7 +16,11 @@ describe Dendroid::Lexical::Literal do
16
16
  expect { described_class.new(ex_source, ex_pos, ex_terminal, ex_value) }.not_to raise_error
17
17
  end
18
18
 
19
- it 'knows its value' do
19
+ it 'knows it is a token with a literal value attached to it' do
20
+ expect(subject).to be_literal
21
+ end
22
+
23
+ it 'knows its literal value' do
20
24
  expect(subject.value).to eq(ex_value)
21
25
  end
22
26
  end # context
@@ -27,5 +27,9 @@ describe Dendroid::Lexical::Token do
27
27
  it 'knows the terminal name' do
28
28
  expect(subject.terminal).to eq(ex_terminal)
29
29
  end
30
+
31
+ it 'has no literal value attached to it' do
32
+ expect(subject).not_to be_literal
33
+ end
30
34
  end # context
31
35
  end # describe
@@ -45,37 +45,37 @@ RSpec.describe Dendroid::Parsing::ChartWalker do
45
45
  walker = described_class.new(chart)
46
46
  root = walker.walk(success_entry(chart, recognizer))
47
47
 
48
- expect(root.to_s).to eq('p => s [0, 5]')
48
+ expect(root.to_s).to eq('p => s [0..5]')
49
49
  expect(root.children.size).to eq(1)
50
- expect(root.children[-1].to_s).to eq('s => s PLUS m [0, 5]')
50
+ expect(root.children[-1].to_s).to eq('s => s PLUS m [0..5]')
51
51
  plus_expr = root.children[-1]
52
52
  expect(plus_expr.children.size).to eq(3)
53
- expect(plus_expr.children[0].to_s).to eq('s => m [0, 1]')
54
- expect(plus_expr.children[1].to_s).to eq('PLUS [1, 2]')
55
- expect(plus_expr.children[2].to_s).to eq('m => m STAR t [2, 5]')
53
+ expect(plus_expr.children[0].to_s).to eq('s => m [0..1]')
54
+ expect(plus_expr.children[1].to_s).to eq('PLUS [1..2]')
55
+ expect(plus_expr.children[2].to_s).to eq('m => m STAR t [2..5]')
56
56
 
57
57
  operand_plus = plus_expr.children[0]
58
58
  expect(operand_plus.children.size).to eq(1)
59
- expect(operand_plus.children[0].to_s).to eq('m => t [0, 1]')
59
+ expect(operand_plus.children[0].to_s).to eq('m => t [0..1]')
60
60
  expect(operand_plus.children[0].children.size).to eq(1)
61
- expect(operand_plus.children[0].children[0].to_s).to eq('t => INTEGER [0, 1]')
62
- expect(operand_plus.children[0].children[0].children[0].to_s).to eq('INTEGER: 2 [0, 1]')
61
+ expect(operand_plus.children[0].children[0].to_s).to eq('t => INTEGER [0..1]')
62
+ expect(operand_plus.children[0].children[0].children[0].to_s).to eq('INTEGER: 2 [0..1]')
63
63
 
64
- expect(plus_expr.children[1].to_s).to eq('PLUS [1, 2]')
64
+ expect(plus_expr.children[1].to_s).to eq('PLUS [1..2]')
65
65
 
66
66
  star_expr = plus_expr.children[2]
67
67
  expect(star_expr.children.size).to eq(3)
68
- expect(star_expr.children[0].to_s).to eq('m => t [2, 3]')
69
- expect(star_expr.children[1].to_s).to eq('STAR [3, 4]')
70
- expect(star_expr.children[2].to_s).to eq('t => INTEGER [4, 5]')
68
+ expect(star_expr.children[0].to_s).to eq('m => t [2..3]')
69
+ expect(star_expr.children[1].to_s).to eq('STAR [3..4]')
70
+ expect(star_expr.children[2].to_s).to eq('t => INTEGER [4..5]')
71
71
 
72
72
  operand_star = star_expr.children[0]
73
73
  expect(operand_star.children.size).to eq(1)
74
- expect(operand_star.children[0].to_s).to eq('t => INTEGER [2, 3]')
75
- expect(operand_star.children[0].children[0].to_s).to eq('INTEGER: 3 [2, 3]')
74
+ expect(operand_star.children[0].to_s).to eq('t => INTEGER [2..3]')
75
+ expect(operand_star.children[0].children[0].to_s).to eq('INTEGER: 3 [2..3]')
76
76
 
77
77
  expect(star_expr.children[2].children.size).to eq(1)
78
- expect(star_expr.children[2].children[0].to_s).to eq('INTEGER: 4 [4, 5]')
78
+ expect(star_expr.children[2].children[0].to_s).to eq('INTEGER: 4 [4..5]')
79
79
  end
80
80
 
81
81
  it 'generates a parse tree for grammar l10 (with left recursive rule)' do
@@ -84,27 +84,27 @@ RSpec.describe Dendroid::Parsing::ChartWalker do
84
84
  walker = described_class.new(chart)
85
85
  root = walker.walk(success_entry(chart, recognizer))
86
86
 
87
- expect(root.to_s).to eq('A => A a [0, 5]')
87
+ expect(root.to_s).to eq('A => A a [0..5]')
88
88
  expect(root.children.size).to eq(2)
89
- expect(root.children[0].to_s).to eq('A => A a [0, 4]')
90
- expect(root.children[1].to_s).to eq('a [4, 5]')
89
+ expect(root.children[0].to_s).to eq('A => A a [0..4]')
90
+ expect(root.children[1].to_s).to eq('a [4..5]')
91
91
 
92
92
  expect(root.children[0].children.size).to eq(2)
93
- expect(root.children[0].children[0].to_s).to eq('A => A a [0, 3]')
94
- expect(root.children[0].children[1].to_s).to eq('a [3, 4]')
93
+ expect(root.children[0].children[0].to_s).to eq('A => A a [0..3]')
94
+ expect(root.children[0].children[1].to_s).to eq('a [3..4]')
95
95
 
96
96
  grand_child = root.children[0].children[0]
97
97
  expect(grand_child.children.size).to eq(2)
98
- expect(grand_child.children[0].to_s).to eq('A => A a [0, 2]')
99
- expect(grand_child.children[1].to_s).to eq('a [2, 3]')
98
+ expect(grand_child.children[0].to_s).to eq('A => A a [0..2]')
99
+ expect(grand_child.children[1].to_s).to eq('a [2..3]')
100
100
 
101
101
  expect(grand_child.children[0].children.size).to eq(2)
102
- expect(grand_child.children[0].children[0].to_s).to eq('A => A a [0, 1]')
103
- expect(grand_child.children[0].children[1].to_s).to eq('a [1, 2]')
102
+ expect(grand_child.children[0].children[0].to_s).to eq('A => A a [0..1]')
103
+ expect(grand_child.children[0].children[1].to_s).to eq('a [1..2]')
104
104
 
105
105
  expect(grand_child.children[0].children[0].children.size).to eq(2)
106
- expect(grand_child.children[0].children[0].children[0].to_s).to eq('_ [0, 0]')
107
- expect(grand_child.children[0].children[0].children[1].to_s).to eq('a [0, 1]')
106
+ expect(grand_child.children[0].children[0].children[0].to_s).to eq('_ [0..0]')
107
+ expect(grand_child.children[0].children[0].children[1].to_s).to eq('a [0..1]')
108
108
  end
109
109
 
110
110
  it 'generates a parse tree for grammar l11 (with right recursive rule)' do
@@ -113,27 +113,27 @@ RSpec.describe Dendroid::Parsing::ChartWalker do
113
113
  walker = described_class.new(chart)
114
114
  root = walker.walk(success_entry(chart, recognizer))
115
115
 
116
- expect(root.to_s).to eq('A => a A [0, 5]')
116
+ expect(root.to_s).to eq('A => a A [0..5]')
117
117
  expect(root.children.size).to eq(2)
118
- expect(root.children[0].to_s).to eq('a [0, 1]')
119
- expect(root.children[1].to_s).to eq('A => a A [1, 5]')
118
+ expect(root.children[0].to_s).to eq('a [0..1]')
119
+ expect(root.children[1].to_s).to eq('A => a A [1..5]')
120
120
 
121
121
  expect(root.children[1].children.size).to eq(2)
122
- expect(root.children[1].children[0].to_s).to eq('a [1, 2]')
123
- expect(root.children[1].children[1].to_s).to eq('A => a A [2, 5]')
122
+ expect(root.children[1].children[0].to_s).to eq('a [1..2]')
123
+ expect(root.children[1].children[1].to_s).to eq('A => a A [2..5]')
124
124
 
125
125
  grand_child = root.children[1].children[1]
126
126
  expect(grand_child.children.size).to eq(2)
127
- expect(grand_child.children[0].to_s).to eq('a [2, 3]')
128
- expect(grand_child.children[1].to_s).to eq('A => a A [3, 5]')
127
+ expect(grand_child.children[0].to_s).to eq('a [2..3]')
128
+ expect(grand_child.children[1].to_s).to eq('A => a A [3..5]')
129
129
 
130
130
  expect(grand_child.children[1].children.size).to eq(2)
131
- expect(grand_child.children[1].children[0].to_s).to eq('a [3, 4]')
132
- expect(grand_child.children[1].children[1].to_s).to eq('A => a A [4, 5]')
131
+ expect(grand_child.children[1].children[0].to_s).to eq('a [3..4]')
132
+ expect(grand_child.children[1].children[1].to_s).to eq('A => a A [4..5]')
133
133
 
134
134
  expect(grand_child.children[1].children[1].children.size).to eq(2)
135
- expect(grand_child.children[1].children[1].children[0].to_s).to eq('a [4, 5]')
136
- expect(grand_child.children[1].children[1].children[1].to_s).to eq('_ [5, 5]')
135
+ expect(grand_child.children[1].children[1].children[0].to_s).to eq('a [4..5]')
136
+ expect(grand_child.children[1].children[1].children[1].to_s).to eq('_ [5..5]')
137
137
  end
138
138
  end # context
139
139
 
@@ -144,78 +144,78 @@ RSpec.describe Dendroid::Parsing::ChartWalker do
144
144
  walker = described_class.new(chart)
145
145
  root = walker.walk(success_entry(chart, recognizer))
146
146
 
147
- expect(root.to_s).to eq('OR: S [0, 4]')
147
+ expect(root.to_s).to eq('OR: S [0..4]')
148
148
  expect(root.children.size).to eq(3)
149
149
  root.children.each do |child|
150
150
  expect(child.children.size).to eq(2)
151
- expect(child.to_s).to eq('S => S S [0, 4]')
151
+ expect(child.to_s).to eq('S => S S [0..4]')
152
152
  end
153
153
  (a, b, c) = root.children
154
154
 
155
155
  # Test structure of tree a
156
156
  (child_a_0, child_a_1) = a.children
157
- expect(child_a_0.to_s).to eq('S => S S [0, 2]')
158
- expect(child_a_1.to_s).to eq('S => S S [2, 4]')
157
+ expect(child_a_0.to_s).to eq('S => S S [0..2]')
158
+ expect(child_a_1.to_s).to eq('S => S S [2..4]')
159
159
  expect(child_a_0.children.size).to eq(2)
160
160
  (child_a_0_0, child_a_0_1) = child_a_0.children
161
- expect(child_a_0_0.to_s).to eq('S => x [0, 1]')
162
- expect(child_a_0_1.to_s).to eq('S => x [1, 2]')
163
- expect(child_a_0_0.children[0].to_s).to eq('x [0, 1]')
164
- expect(child_a_0_1.children[0].to_s).to eq('x [1, 2]')
161
+ expect(child_a_0_0.to_s).to eq('S => x [0..1]')
162
+ expect(child_a_0_1.to_s).to eq('S => x [1..2]')
163
+ expect(child_a_0_0.children[0].to_s).to eq('x [0..1]')
164
+ expect(child_a_0_1.children[0].to_s).to eq('x [1..2]')
165
165
 
166
166
  expect(child_a_1.children.size).to eq(2)
167
167
  (child_a_1_0, child_a_1_1) = child_a_1.children
168
- expect(child_a_1_0.to_s).to eq('S => x [2, 3]')
169
- expect(child_a_1_1.to_s).to eq('S => x [3, 4]')
170
- expect(child_a_1_0.children[0].to_s).to eq('x [2, 3]')
171
- expect(child_a_1_1.children[0].to_s).to eq('x [3, 4]')
168
+ expect(child_a_1_0.to_s).to eq('S => x [2..3]')
169
+ expect(child_a_1_1.to_s).to eq('S => x [3..4]')
170
+ expect(child_a_1_0.children[0].to_s).to eq('x [2..3]')
171
+ expect(child_a_1_1.children[0].to_s).to eq('x [3..4]')
172
172
 
173
173
  # Test structure of forest b
174
174
  (child_b_0, child_b_1) = b.children
175
- expect(child_b_0.to_s).to eq('OR: S [0, 3]')
176
- expect(child_b_1.to_s).to eq('S => x [3, 4]')
175
+ expect(child_b_0.to_s).to eq('OR: S [0..3]')
176
+ expect(child_b_1.to_s).to eq('S => x [3..4]')
177
177
  expect(child_b_1.equal?(child_a_1_1)).to be_truthy # Sharing
178
178
  expect(child_b_0.children.size).to eq(2)
179
179
  (child_b_0_0, child_b_0_1) = child_b_0.children
180
- expect(child_b_0_0.to_s).to eq('S => S S [0, 3]')
181
- expect(child_b_0_1.to_s).to eq('S => S S [0, 3]')
180
+ expect(child_b_0_0.to_s).to eq('S => S S [0..3]')
181
+ expect(child_b_0_1.to_s).to eq('S => S S [0..3]')
182
182
  expect(child_b_0_0.children.size).to eq(2)
183
183
  (child_b_0_0_0, child_b_0_0_1) = child_b_0_0.children
184
- expect(child_b_0_0_0.to_s).to eq('S => x [0, 1]')
184
+ expect(child_b_0_0_0.to_s).to eq('S => x [0..1]')
185
185
  expect(child_b_0_0_0.equal?(child_a_0_0)).to be_truthy # Sharing
186
- expect(child_b_0_0_1.to_s).to eq('S => S S [1, 3]')
186
+ expect(child_b_0_0_1.to_s).to eq('S => S S [1..3]')
187
187
  expect(child_b_0_0_1.children.size).to eq(2)
188
- expect(child_b_0_0_1.children[0].to_s).to eq('S => x [1, 2]')
188
+ expect(child_b_0_0_1.children[0].to_s).to eq('S => x [1..2]')
189
189
  expect(child_b_0_0_1.children[0].equal?(child_a_0_1)).to be_truthy # Sharing
190
- expect(child_b_0_0_1.children[1].to_s).to eq('S => x [2, 3]')
190
+ expect(child_b_0_0_1.children[1].to_s).to eq('S => x [2..3]')
191
191
  expect(child_b_0_0_1.children[1].equal?(child_a_1_0)).to be_truthy # Sharing
192
192
 
193
193
  expect(child_b_0_1.children.size).to eq(2)
194
194
  (child_b_0_1_0, child_b_0_1_1) = child_b_0_1.children
195
- expect(child_b_0_1_0.to_s).to eq('S => S S [0, 2]')
195
+ expect(child_b_0_1_0.to_s).to eq('S => S S [0..2]')
196
196
  expect(child_b_0_1_0.equal?(child_a_0)).to be_truthy # Sharing
197
- expect(child_b_0_1_1.to_s).to eq('S => x [2, 3]')
197
+ expect(child_b_0_1_1.to_s).to eq('S => x [2..3]')
198
198
  expect(child_b_0_1_1.equal?(child_a_1_0)).to be_truthy # Sharing
199
199
 
200
200
  # Test structure of forest c
201
201
  (child_c_0, child_c_1) = c.children
202
- expect(child_c_0.to_s).to eq('S => x [0, 1]')
202
+ expect(child_c_0.to_s).to eq('S => x [0..1]')
203
203
  expect(child_c_0.equal?(child_a_0_0)).to be_truthy # Sharing
204
- expect(child_c_1.to_s).to eq('OR: S [1, 4]')
204
+ expect(child_c_1.to_s).to eq('OR: S [1..4]')
205
205
  expect(child_c_1.children.size).to eq(2)
206
206
  (child_c_1_0, child_c_1_1) = child_c_1.children
207
- expect(child_c_1_0.to_s).to eq('S => S S [1, 4]')
208
- expect(child_c_1_1.to_s).to eq('S => S S [1, 4]')
207
+ expect(child_c_1_0.to_s).to eq('S => S S [1..4]')
208
+ expect(child_c_1_1.to_s).to eq('S => S S [1..4]')
209
209
  expect(child_c_1_0.children.size).to eq(2)
210
210
  (child_c_1_0_0, child_c_1_0_1) = child_c_1_0.children
211
- expect(child_c_1_0_0.to_s).to eq('S => x [1, 2]')
211
+ expect(child_c_1_0_0.to_s).to eq('S => x [1..2]')
212
212
  expect(child_c_1_0_0.equal?(child_a_0_1)).to be_truthy # Sharing
213
- expect(child_c_1_0_1.to_s).to eq('S => S S [2, 4]')
213
+ expect(child_c_1_0_1.to_s).to eq('S => S S [2..4]')
214
214
  expect(child_c_1_0_1.equal?(child_a_1)).to be_truthy # Sharing
215
215
  (child_c_1_1_0, child_c_1_1_1) = child_c_1_1.children
216
- expect(child_c_1_1_0.to_s).to eq('S => S S [1, 3]')
216
+ expect(child_c_1_1_0.to_s).to eq('S => S S [1..3]')
217
217
  expect(child_c_1_1_0.equal?(child_b_0_0_1)).to be_truthy # Sharing
218
- expect(child_c_1_1_1.to_s).to eq('S => x [3, 4]')
218
+ expect(child_c_1_1_1.to_s).to eq('S => x [3..4]')
219
219
  expect(child_c_1_1_1.equal?(child_b_1)).to be_truthy # Sharing
220
220
  end
221
221
 
@@ -225,24 +225,24 @@ RSpec.describe Dendroid::Parsing::ChartWalker do
225
225
  walker = described_class.new(chart)
226
226
  root = walker.walk(success_entry(chart, recognizer))
227
227
 
228
- expect(root.to_s).to eq('OR: S [0, 2]')
228
+ expect(root.to_s).to eq('OR: S [0..2]')
229
229
  expect(root.children.size).to eq(2)
230
230
  root.children.each do |ch|
231
- expect(ch.to_s).to eq('S => S T [0, 2]')
231
+ expect(ch.to_s).to eq('S => S T [0..2]')
232
232
  expect(ch.children.size).to eq(2)
233
233
  end
234
234
  (child_0_0, child_0_1) = root.children[0].children
235
- expect(child_0_0.to_s).to eq('S => a [0, 1]')
236
- expect(child_0_1.to_s).to eq('T => a B [1, 2]')
235
+ expect(child_0_0.to_s).to eq('S => a [0..1]')
236
+ expect(child_0_1.to_s).to eq('T => a B [1..2]')
237
237
  expect(child_0_1.children.size).to eq(2)
238
- expect(child_0_1.children[0].to_s).to eq('a [1, 2]')
239
- expect(child_0_1.children[1].to_s).to eq('_ [2, 2]')
238
+ expect(child_0_1.children[0].to_s).to eq('a [1..2]')
239
+ expect(child_0_1.children[1].to_s).to eq('_ [2..2]')
240
240
 
241
241
  (child_1_0, child_1_1) = root.children[1].children
242
- expect(child_1_0.to_s).to eq('S => a [0, 1]')
243
- expect(child_1_1.to_s).to eq('T => a [1, 2]')
242
+ expect(child_1_0.to_s).to eq('S => a [0..1]')
243
+ expect(child_1_1.to_s).to eq('T => a [1..2]')
244
244
  expect(child_1_0.equal?(child_0_0)).to be_truthy # Sharing
245
- expect(child_1_1.children[0].to_s).to eq('a [1, 2]')
245
+ expect(child_1_1.children[0].to_s).to eq('a [1..2]')
246
246
  expect(child_1_1.children[0].equal?(child_0_1.children[0])).to be_truthy # Sharing
247
247
  end
248
248
  end # context
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+
5
+ require_relative '../../../lib/dendroid/parsing/composite_parse_node'
6
+
7
+ RSpec.describe Dendroid::Parsing::CompositeParseNode do
8
+ let(:sample_range) { 3..5 }
9
+ let(:sample_child_count) { 7 }
10
+ subject { described_class.new(sample_range.begin, sample_range.end, sample_child_count) }
11
+
12
+ context 'Initialization:' do
13
+ it 'should be initialized with two token positions and a child count' do
14
+ expect { described_class.new(sample_range.begin, sample_range.end, sample_child_count) }.not_to raise_error
15
+ end
16
+
17
+ it 'has its children array filled with nils' do
18
+ # Check number of elements...
19
+ expect(subject.children.size).to eq(sample_child_count)
20
+
21
+ # All elements are nil
22
+ expect(subject.children.all?(&:nil?)).to be_truthy
23
+ end
24
+ end # context
25
+
26
+ context 'provided services:' do
27
+ it 'adds a child node at a specific slot' do
28
+ child3 = Dendroid::Parsing::ParseNode.new(3, 4)
29
+ child5 = Dendroid::Parsing::ParseNode.new(5, 6)
30
+ subject.add_child(child3, 3)
31
+ subject.add_child(child5, 5)
32
+ expect(subject.children.reject(&:nil?).size).to eq(2)
33
+ expect(subject.children[3]).to eq(child3)
34
+ expect(subject.children[5]).to eq(child5)
35
+ end
36
+ end # context
37
+ end # describe
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+ require_relative '../../../lib/dendroid/grm_dsl/base_grm_builder'
5
+ require_relative '../../../lib/dendroid/grm_analysis/dotted_item'
6
+ require_relative '../../../lib/dendroid/recognizer/e_item'
7
+ require_relative '../../../lib/dendroid/parsing/empty_rule_node'
8
+
9
+ RSpec.describe Dendroid::Parsing::EmptyRuleNode do
10
+ let(:sample_rule) { sample_grammar.rules[0] }
11
+ let(:sample_dotted_item) { Dendroid::GrmAnalysis::DottedItem.new(sample_rule, 0, 1) }
12
+ let(:sample_entry) { Dendroid::Recognizer::EItem.new(sample_dotted_item, 5) }
13
+
14
+ subject { described_class.new(sample_entry, 5) }
15
+
16
+ let(:sample_grammar) do
17
+ builder = Dendroid::GrmDSL::BaseGrmBuilder.new do
18
+ declare_terminals('INTEGER')
19
+
20
+ rule('s' => ['INTEGER', ''])
21
+ end
22
+
23
+ builder.grammar
24
+ end
25
+
26
+ context 'Initialization:' do
27
+ it 'should be initialized with a chart entry and an end rank number' do
28
+ expect { described_class.new(sample_entry, 5) }.not_to raise_error
29
+ end
30
+
31
+ it 'knows the rule it is related to' do
32
+ expect(subject.rule).to eq(sample_grammar.rules[0])
33
+ end
34
+
35
+ it 'knows the alternative index it is related to' do
36
+ expect(subject.alt_index).to eq(1)
37
+ end
38
+
39
+ it 'knows its origin and end positions' do
40
+ expect(subject.range.begin).to eq(subject.range.end)
41
+ expect(subject.range.begin).to eq(5)
42
+ end
43
+ end # context
44
+
45
+ context 'Provided services:' do
46
+ it 'renders a String representation of its range' do
47
+ expect(subject.to_s).to eq('_ [5..5]')
48
+ end
49
+ end # context
50
+ end # describe
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+ require_relative '../../../lib/dendroid/parsing/parse_node'
5
+
6
+ RSpec.describe Dendroid::Parsing::ParseNode do
7
+ let(:sample_range) { 3..5 }
8
+ subject { described_class.new(3, 5) }
9
+
10
+ context 'Initialization:' do
11
+ it 'should be initialized with two token positions' do
12
+ expect { described_class.new(3, 5) }.not_to raise_error
13
+ end
14
+
15
+ it 'knows its origin and end positions' do
16
+ expect(subject.range).to eq(sample_range)
17
+ end
18
+ end # context
19
+
20
+ context 'Provided services:' do
21
+ it 'renders a String representation of its range' do
22
+ expect(subject.send(:range_to_s)).to eq('[3..5]')
23
+ end
24
+ end # context
25
+ end # describe
@@ -22,15 +22,15 @@ RSpec.describe Dendroid::Parsing::TerminalNode do
22
22
  it 'should be initialized with a symbol, terminal and a rank' do
23
23
  expect { described_class.new(ex_terminal, plus_token, 3) }.not_to raise_error
24
24
  end
25
- end
25
+ end # context
26
26
 
27
- context 'provided services' do
27
+ context 'provided services:' do
28
28
  it 'renders a String representation of itself' do
29
- expect(plus_node.to_s).to eq('PLUS [3, 4]')
29
+ expect(plus_node.to_s).to eq('PLUS [3..4]')
30
30
  end
31
31
 
32
32
  it 'renders also the token value (if any)' do
33
- expect(int_node.to_s).to eq('INTEGER: 2 [5, 6]')
33
+ expect(int_node.to_s).to eq('INTEGER: 2 [5..6]')
34
34
  end
35
35
  end
36
36
  end
data/version.txt CHANGED
@@ -1 +1 @@
1
- 0.2.02
1
+ 0.2.03
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dendroid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.02
4
+ version: 0.2.03
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-18 00:00:00.000000000 Z
11
+ date: 2023-12-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: WIP. A Ruby implementation of an Earley parser
14
14
  email: famished.tiger@yahoo.com
@@ -62,6 +62,9 @@ files:
62
62
  - spec/dendroid/lexical/token_position_spec.rb
63
63
  - spec/dendroid/lexical/token_spec.rb
64
64
  - spec/dendroid/parsing/chart_walker_spec.rb
65
+ - spec/dendroid/parsing/composite_parse_node_spec.rb
66
+ - spec/dendroid/parsing/empty_rule_node_spec.rb
67
+ - spec/dendroid/parsing/parse_node_spec.rb
65
68
  - spec/dendroid/parsing/terminal_node_spec.rb
66
69
  - spec/dendroid/recognizer/chart_spec.rb
67
70
  - spec/dendroid/recognizer/e_item_spec.rb