rley 0.7.06 → 0.8.01

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +362 -62
  3. data/.travis.yml +6 -6
  4. data/CHANGELOG.md +20 -4
  5. data/LICENSE.txt +1 -1
  6. data/README.md +7 -7
  7. data/examples/NLP/engtagger.rb +193 -190
  8. data/examples/NLP/nano_eng/nano_en_demo.rb +7 -11
  9. data/examples/NLP/nano_eng/nano_grammar.rb +21 -21
  10. data/examples/NLP/pico_en_demo.rb +2 -2
  11. data/examples/data_formats/JSON/cli_options.rb +1 -1
  12. data/examples/data_formats/JSON/json_ast_builder.rb +21 -27
  13. data/examples/data_formats/JSON/json_ast_nodes.rb +12 -21
  14. data/examples/data_formats/JSON/json_demo.rb +1 -2
  15. data/examples/data_formats/JSON/json_grammar.rb +13 -13
  16. data/examples/data_formats/JSON/json_lexer.rb +8 -8
  17. data/examples/data_formats/JSON/json_minifier.rb +1 -1
  18. data/examples/general/calc_iter1/calc_ast_builder.rb +13 -10
  19. data/examples/general/calc_iter1/calc_ast_nodes.rb +23 -37
  20. data/examples/general/calc_iter1/calc_grammar.rb +7 -6
  21. data/examples/general/calc_iter1/calc_lexer.rb +6 -4
  22. data/examples/general/calc_iter1/spec/calculator_spec.rb +5 -5
  23. data/examples/general/calc_iter2/calc_ast_builder.rb +5 -3
  24. data/examples/general/calc_iter2/calc_ast_nodes.rb +27 -43
  25. data/examples/general/calc_iter2/calc_grammar.rb +12 -12
  26. data/examples/general/calc_iter2/calc_lexer.rb +11 -10
  27. data/examples/general/calc_iter2/spec/calculator_spec.rb +26 -26
  28. data/examples/general/left.rb +2 -2
  29. data/examples/general/right.rb +2 -2
  30. data/lib/rley.rb +1 -1
  31. data/lib/rley/base/dotted_item.rb +28 -31
  32. data/lib/rley/base/grm_items_builder.rb +6 -0
  33. data/lib/rley/constants.rb +2 -2
  34. data/lib/rley/engine.rb +22 -25
  35. data/lib/rley/formatter/asciitree.rb +3 -3
  36. data/lib/rley/formatter/bracket_notation.rb +1 -8
  37. data/lib/rley/formatter/debug.rb +6 -6
  38. data/lib/rley/formatter/json.rb +2 -2
  39. data/lib/rley/gfg/call_edge.rb +1 -1
  40. data/lib/rley/gfg/edge.rb +5 -5
  41. data/lib/rley/gfg/end_vertex.rb +2 -6
  42. data/lib/rley/gfg/epsilon_edge.rb +1 -5
  43. data/lib/rley/gfg/grm_flow_graph.rb +27 -23
  44. data/lib/rley/gfg/item_vertex.rb +10 -10
  45. data/lib/rley/gfg/non_terminal_vertex.rb +4 -4
  46. data/lib/rley/gfg/scan_edge.rb +1 -1
  47. data/lib/rley/gfg/shortcut_edge.rb +2 -2
  48. data/lib/rley/gfg/start_vertex.rb +4 -8
  49. data/lib/rley/gfg/vertex.rb +43 -39
  50. data/lib/rley/interface.rb +16 -0
  51. data/lib/rley/lexical/token_range.rb +6 -6
  52. data/lib/rley/notation/all_notation_nodes.rb +2 -0
  53. data/lib/rley/notation/ast_builder.rb +191 -0
  54. data/lib/rley/notation/ast_node.rb +44 -0
  55. data/lib/rley/notation/ast_visitor.rb +113 -0
  56. data/lib/rley/notation/grammar.rb +49 -0
  57. data/lib/rley/notation/grammar_builder.rb +504 -0
  58. data/lib/rley/notation/grouping_node.rb +23 -0
  59. data/lib/rley/notation/parser.rb +56 -0
  60. data/lib/rley/notation/sequence_node.rb +35 -0
  61. data/lib/rley/notation/symbol_node.rb +29 -0
  62. data/lib/rley/notation/tokenizer.rb +192 -0
  63. data/lib/rley/parse_forest_visitor.rb +5 -5
  64. data/lib/rley/parse_rep/ast_base_builder.rb +48 -11
  65. data/lib/rley/parse_rep/cst_builder.rb +5 -6
  66. data/lib/rley/parse_rep/parse_forest_builder.rb +22 -18
  67. data/lib/rley/parse_rep/parse_forest_factory.rb +3 -3
  68. data/lib/rley/parse_rep/parse_rep_creator.rb +14 -16
  69. data/lib/rley/parse_rep/parse_tree_builder.rb +4 -4
  70. data/lib/rley/parse_rep/parse_tree_factory.rb +27 -27
  71. data/lib/rley/parse_tree_visitor.rb +1 -1
  72. data/lib/rley/parser/error_reason.rb +4 -5
  73. data/lib/rley/parser/gfg_chart.rb +118 -26
  74. data/lib/rley/parser/gfg_parsing.rb +22 -33
  75. data/lib/rley/parser/parse_entry.rb +25 -31
  76. data/lib/rley/parser/parse_entry_set.rb +19 -16
  77. data/lib/rley/parser/parse_entry_tracker.rb +4 -4
  78. data/lib/rley/parser/parse_tracer.rb +13 -13
  79. data/lib/rley/parser/parse_walker_factory.rb +23 -28
  80. data/lib/rley/ptree/non_terminal_node.rb +7 -5
  81. data/lib/rley/ptree/parse_tree.rb +3 -3
  82. data/lib/rley/ptree/parse_tree_node.rb +5 -5
  83. data/lib/rley/ptree/terminal_node.rb +7 -7
  84. data/lib/rley/rley_error.rb +12 -12
  85. data/lib/rley/sppf/alternative_node.rb +6 -6
  86. data/lib/rley/sppf/composite_node.rb +7 -7
  87. data/lib/rley/sppf/epsilon_node.rb +3 -3
  88. data/lib/rley/sppf/leaf_node.rb +3 -3
  89. data/lib/rley/sppf/parse_forest.rb +16 -16
  90. data/lib/rley/sppf/sppf_node.rb +7 -8
  91. data/lib/rley/sppf/token_node.rb +3 -3
  92. data/lib/rley/syntax/{grammar_builder.rb → base_grammar_builder.rb} +61 -23
  93. data/lib/rley/syntax/grammar.rb +5 -5
  94. data/lib/rley/syntax/grm_symbol.rb +7 -7
  95. data/lib/rley/syntax/match_closest.rb +43 -0
  96. data/lib/rley/syntax/non_terminal.rb +9 -15
  97. data/lib/rley/syntax/production.rb +16 -10
  98. data/lib/rley/syntax/symbol_seq.rb +7 -9
  99. data/lib/rley/syntax/terminal.rb +4 -5
  100. data/lib/rley/syntax/verbatim_symbol.rb +3 -3
  101. data/lib/support/base_tokenizer.rb +19 -18
  102. data/spec/rley/base/dotted_item_spec.rb +2 -2
  103. data/spec/rley/engine_spec.rb +23 -21
  104. data/spec/rley/formatter/asciitree_spec.rb +7 -7
  105. data/spec/rley/formatter/bracket_notation_spec.rb +13 -13
  106. data/spec/rley/formatter/json_spec.rb +1 -1
  107. data/spec/rley/gfg/end_vertex_spec.rb +5 -5
  108. data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -2
  109. data/spec/rley/gfg/item_vertex_spec.rb +10 -10
  110. data/spec/rley/gfg/non_terminal_vertex_spec.rb +3 -3
  111. data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
  112. data/spec/rley/gfg/start_vertex_spec.rb +5 -5
  113. data/spec/rley/gfg/vertex_spec.rb +3 -3
  114. data/spec/rley/lexical/token_range_spec.rb +16 -16
  115. data/spec/rley/lexical/token_spec.rb +2 -2
  116. data/spec/rley/notation/grammar_builder_spec.rb +302 -0
  117. data/spec/rley/notation/parser_spec.rb +184 -0
  118. data/spec/rley/notation/tokenizer_spec.rb +370 -0
  119. data/spec/rley/parse_forest_visitor_spec.rb +165 -163
  120. data/spec/rley/parse_rep/ambiguous_parse_spec.rb +44 -44
  121. data/spec/rley/parse_rep/ast_builder_spec.rb +6 -7
  122. data/spec/rley/parse_rep/cst_builder_spec.rb +5 -5
  123. data/spec/rley/parse_rep/groucho_spec.rb +24 -26
  124. data/spec/rley/parse_rep/parse_forest_builder_spec.rb +27 -27
  125. data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -8
  126. data/spec/rley/parse_rep/parse_tree_factory_spec.rb +3 -3
  127. data/spec/rley/parse_tree_visitor_spec.rb +10 -8
  128. data/spec/rley/parser/dangling_else_spec.rb +445 -0
  129. data/spec/rley/parser/error_reason_spec.rb +6 -6
  130. data/spec/rley/parser/gfg_earley_parser_spec.rb +120 -12
  131. data/spec/rley/parser/gfg_parsing_spec.rb +6 -13
  132. data/spec/rley/parser/parse_entry_spec.rb +19 -19
  133. data/spec/rley/parser/parse_walker_factory_spec.rb +10 -10
  134. data/spec/rley/ptree/non_terminal_node_spec.rb +5 -3
  135. data/spec/rley/ptree/parse_tree_node_spec.rb +4 -4
  136. data/spec/rley/ptree/terminal_node_spec.rb +6 -6
  137. data/spec/rley/sppf/alternative_node_spec.rb +6 -6
  138. data/spec/rley/sppf/non_terminal_node_spec.rb +3 -3
  139. data/spec/rley/sppf/token_node_spec.rb +4 -4
  140. data/spec/rley/support/ambiguous_grammar_helper.rb +4 -5
  141. data/spec/rley/support/grammar_abc_helper.rb +3 -5
  142. data/spec/rley/support/grammar_ambig01_helper.rb +5 -6
  143. data/spec/rley/support/grammar_arr_int_helper.rb +5 -6
  144. data/spec/rley/support/grammar_b_expr_helper.rb +5 -6
  145. data/spec/rley/support/grammar_int_seq_helper.rb +51 -0
  146. data/spec/rley/support/grammar_l0_helper.rb +14 -17
  147. data/spec/rley/support/grammar_pb_helper.rb +8 -7
  148. data/spec/rley/support/grammar_sppf_helper.rb +3 -3
  149. data/spec/rley/syntax/{grammar_builder_spec.rb → base_grammar_builder_spec.rb} +35 -16
  150. data/spec/rley/syntax/grammar_spec.rb +6 -6
  151. data/spec/rley/syntax/grm_symbol_spec.rb +1 -1
  152. data/spec/rley/syntax/match_closest_spec.rb +46 -0
  153. data/spec/rley/syntax/non_terminal_spec.rb +8 -8
  154. data/spec/rley/syntax/production_spec.rb +17 -13
  155. data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
  156. data/spec/rley/syntax/terminal_spec.rb +5 -5
  157. data/spec/rley/syntax/verbatim_symbol_spec.rb +1 -1
  158. data/spec/spec_helper.rb +0 -12
  159. data/spec/support/base_tokenizer_spec.rb +7 -2
  160. metadata +48 -74
  161. data/.simplecov +0 -7
  162. data/lib/rley/parser/parse_state.rb +0 -83
  163. data/lib/rley/parser/parse_state_tracker.rb +0 -59
  164. data/lib/rley/parser/state_set.rb +0 -101
  165. data/spec/rley/parser/parse_state_spec.rb +0 -125
  166. data/spec/rley/parser/parse_tracer_spec.rb +0 -200
  167. data/spec/rley/parser/state_set_spec.rb +0 -130
@@ -40,33 +40,33 @@ module Rley # This module is used as a namespace
40
40
  # The label of this vertex.
41
41
  # It is the same as the label of the corresponding dotted item.
42
42
  # @return [String] Label for this vertex
43
- def label()
44
- return dotted_item.to_s
43
+ def label
44
+ dotted_item.to_s
45
45
  end
46
46
 
47
47
  # Returns true if the dotted item has a dot at the end of the production.
48
48
  # @return [Boolean]
49
- def complete?()
50
- return dotted_item.reduce_item?
49
+ def complete?
50
+ dotted_item.reduce_item?
51
51
  end
52
52
 
53
53
  # Return the symbol before the dot.
54
54
  # @return [Syntax::GrmSymbol, NilClass] Previous symbol otherwise nil.
55
- def prev_symbol()
56
- return dotted_item.prev_symbol
55
+ def prev_symbol
56
+ dotted_item.prev_symbol
57
57
  end
58
58
 
59
59
  # Return the symbol after the dot.
60
60
  # @return [Syntax::GrmSymbol, NilClass] Next grammar symbol otherwise nil.
61
- def next_symbol()
62
- return dotted_item.next_symbol
61
+ def next_symbol
62
+ @next_symbol ||= dotted_item.next_symbol
63
63
  end
64
64
 
65
65
  # Return the non-terminal symbol at the left-hand side of the production
66
66
  # @return [Syntax::GrmSymbol]
67
67
  # The non-terminal symbol at left side of production.
68
- def lhs()
69
- return dotted_item.lhs
68
+ def lhs
69
+ dotted_item.lhs
70
70
  end
71
71
  end # class
72
72
  end # module
@@ -5,7 +5,7 @@ require_relative 'vertex'
5
5
  module Rley # This module is used as a namespace
6
6
  module GFG # This module is used as a namespace
7
7
  # Abstract class.
8
- # Represents a specialized vertex in a grammar flow graph
8
+ # Represents a specialized vertex in a grammar flow graph
9
9
  # that is associated to a given non-terminal symbol and
10
10
  # that may have in-degree or out-degree > 1
11
11
  # Responsibilities (in addition to inherited ones):
@@ -14,20 +14,20 @@ module Rley # This module is used as a namespace
14
14
  # The non-terminal symbol associated to the vertex
15
15
  # @return [Syntax::NonTerminal]
16
16
  attr_reader :non_terminal
17
-
17
+
18
18
  # Constructor to specialize in subclasses.
19
19
  # @param aNonTerminal [Syntax::NonTerminal]
20
20
  def initialize(aNonTerminal)
21
21
  super()
22
22
  @non_terminal = aNonTerminal
23
23
  end
24
-
24
+
25
25
  protected
26
26
 
27
27
  # Validation method for adding an outgoing edge to the vertex.
28
28
  # A start vertex may accept an indegree and outdegree greater than one
29
29
  def check_add_edge(anEdge)
30
- return anEdge
30
+ anEdge
31
31
  end
32
32
  end # class
33
33
  end # module
@@ -17,7 +17,7 @@ module Rley # This module is used as a namespace
17
17
  @terminal = aTerminal
18
18
  end
19
19
 
20
- def to_s()
20
+ def to_s
21
21
  " -#{terminal}-> #{successor.label}"
22
22
  end
23
23
  end # class
@@ -12,12 +12,12 @@ module Rley # This module is used as a namespace
12
12
  attr_reader :nonterminal
13
13
 
14
14
  def initialize(thePredecessor, theSuccessor)
15
- @successor = theSuccessor
15
+ super(nil, theSuccessor)
16
16
  @nonterminal = thePredecessor.next_symbol
17
17
  thePredecessor.shortcut = self
18
18
  end
19
19
 
20
- def to_s()
20
+ def to_s
21
21
  " -#{nonterminal}-> #{successor.label}"
22
22
  end
23
23
  end # class
@@ -5,19 +5,15 @@ require_relative 'non_terminal_vertex'
5
5
  module Rley # This module is used as a namespace
6
6
  module GFG # This module is used as a namespace
7
7
  # TODO: change definition.
8
- # Represents a specialized vertex in a grammar flow graph
8
+ # Represents a specialized vertex in a grammar flow graph
9
9
  # that is associated to a given non-terminal symbol.
10
10
  # Responsibilities (in addition to inherited ones):
11
11
  # - Know its related non-terminal symbol
12
12
  class StartVertex < NonTerminalVertex
13
- def initialize(aNonTerminal)
14
- super(aNonTerminal)
15
- end
16
-
17
13
  # @return [String]
18
- def label()
19
- return ".#{non_terminal}"
20
- end
14
+ def label
15
+ ".#{non_terminal}"
16
+ end
21
17
  end # class
22
18
  end # module
23
19
  end # module
@@ -10,60 +10,65 @@ module Rley # This module is used as a namespace
10
10
  # The edges linking the successor vertices to this one.
11
11
  # @return [Array<Edge>] The edge(s) linking this vertex to successor(s)
12
12
  attr_reader :edges
13
-
13
+
14
+ # Return the object id in string format
15
+ # @return [String]
16
+ attr_reader :oid_str
17
+
14
18
  # Constructor to extend in subclasses.
15
- def initialize()
19
+ def initialize
16
20
  @edges = []
21
+ @oid_str = object_id.to_s
17
22
  end
18
-
19
- # Add an graph edge to this vertex.
20
- # @param anEdge [Edge] the edge to be added.
21
- def add_edge(anEdge)
22
- arrow = check_add_edge(anEdge)
23
- edges << arrow
24
- end
25
-
26
- # Determine if the vertex corresponds to an dotted item that has
23
+
24
+ # Determine if the vertex corresponds to an dotted item that has
27
25
  # its dot at the end of a production (i.e. is a reduced item).
28
26
  # @return [Boolean] true iff vertex corresponds to reduced item.
29
- def complete?()
30
- return false # Default implementation
27
+ def complete?
28
+ false # Default implementation
31
29
  end
32
-
33
- # Returns a string containing a human-readable representation of the
30
+
31
+ # Returns a string containing a human-readable representation of the
34
32
  # vertex.
35
33
  # @return [String]
36
- def inspect()
34
+ def inspect
37
35
  result = +'#<'
38
36
  result << selfie
39
37
  edges.each { |e| result << e.inspect }
40
38
  result << specific_inspect
41
39
  result << '>'
42
-
43
- return result
40
+
41
+ result
44
42
  end
45
-
46
- # Returns a string containing a human-readable representation of the
43
+
44
+ # Returns a string containing a human-readable representation of the
47
45
  # vertex without the edges.
48
- # @return [String]
49
- def selfie()
46
+ # @return [String]
47
+ def selfie
50
48
  result = +"#{self.class.name}:#{object_id}"
51
49
  result << %( label="#{label}")
52
- return result
50
+ result
53
51
  end
54
-
52
+
55
53
  # Retrieve the grammar symbol before the dot.
56
54
  # @return [GrmSymbol, NilClass] The symbol or otherwise nil.
57
- def prev_symbol()
58
- return nil # Default implementation
59
- end
60
-
55
+ def prev_symbol
56
+ nil # Default implementation
57
+ end
58
+
61
59
  # Retrieve the grammar symbol after the dot.
62
- # @return [GrmSymbol, NilClass] The symbol or otherwise nil.
63
- def next_symbol()
64
- return nil # Default implementation
60
+ # @return [GrmSymbol, NilClass] The symbol or otherwise nil.
61
+ def next_symbol
62
+ nil # Default implementation
63
+ end
64
+
65
+ # Add an graph edge to this vertex.
66
+ # @param anEdge [Edge] the edge to be added.
67
+ def add_edge(anEdge)
68
+ arrow = check_add_edge(anEdge)
69
+ edges << arrow
65
70
  end
66
-
71
+
67
72
  protected
68
73
 
69
74
  # Validation method for adding an outgoing edge to the vertex.
@@ -71,14 +76,13 @@ module Rley # This module is used as a namespace
71
76
  # unless this method is overridden in subclasses
72
77
  def check_add_edge(anEdge)
73
78
  raise StandardError, 'At most one edge accepted' unless edges.empty?
74
-
75
- return anEdge
79
+
80
+ anEdge
81
+ end
82
+
83
+ def specific_inspect
84
+ ''
76
85
  end
77
-
78
- def specific_inspect()
79
- return ''
80
- end
81
-
82
86
  end # class
83
87
  end # module
84
88
  end # module
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './notation/grammar_builder'
4
+
5
+ module Rley # Module used as a namespace
6
+ # Factory method.
7
+ # A grammar builder constructs a Rley grammar piece by piece
8
+ # from DSL instructions in a provided code block.
9
+ # @param aBlock [Proc] a code block
10
+ # @return [Rley::Notation::GrammarBuilder] An object that builds a grammar.
11
+ def self.grammar_builder(&aBlock)
12
+ Rley::Notation::GrammarBuilder.new(&aBlock)
13
+ end
14
+ end # module
15
+
16
+ # End of file
@@ -2,13 +2,13 @@
2
2
 
3
3
  module Rley # This module is used as a namespace
4
4
  module Lexical # This module is used as a namespace
5
- # A token range (also called an extent) represents an interval
5
+ # A token range (also called an extent) represents an interval
6
6
  # of token positions that is matched by a given grammar symbol.
7
7
  # For instance consider the expression E: 3 + 11,
8
8
  # let's assume that the integer literal '3' is the fifth input token and
9
9
  # that the '+' and '11' tokens are respectively at position 6 and 7;
10
10
  # then the token range associated with E is [5, 7]
11
- # While the parse tree/forest is being constructed the boundaries of the
11
+ # While the parse tree/forest is being constructed the boundaries of the
12
12
  # token range can be temporarily undefined (= set to nil)
13
13
  class TokenRange
14
14
  # The index of the lower bound of token range
@@ -47,8 +47,8 @@ module Rley # This module is used as a namespace
47
47
  end
48
48
 
49
49
  # true when both bounds aren't nil.
50
- def bounded?()
51
- return !(low.nil? || high.nil?)
50
+ def bounded?
51
+ !(low.nil? || high.nil?)
52
52
  end
53
53
 
54
54
  # Conditional assign
@@ -73,8 +73,8 @@ module Rley # This module is used as a namespace
73
73
  def to_string(_indentation)
74
74
  low_text = low.nil? ? '?' : low.to_s
75
75
  high_text = high.nil? ? '?' : high.to_s
76
-
77
- return "[#{low_text}, #{high_text}]"
76
+
77
+ "[#{low_text}, #{high_text}]"
78
78
  end
79
79
 
80
80
  private
@@ -0,0 +1,2 @@
1
+ require_relative 'grouping_node'
2
+ require_relative 'symbol_node'
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../parse_rep/ast_base_builder'
4
+ require_relative '../engine'
5
+ require_relative 'all_notation_nodes'
6
+
7
+ module Rley
8
+ module Notation
9
+ # The purpose of ASTBuilder is to build piece by piece an AST
10
+ # (Abstract Syntax Tree) from a sequence of input tokens and
11
+ # visit events produced by walking over a GFGParsing object.
12
+ class ASTBuilder < Rley::ParseRep::ASTBaseBuilder
13
+ unless defined?(Name2special)
14
+ # Mapping Token name => operator | separator | delimiter characters
15
+ # @return [Hash{String => String}]
16
+ Name2special = {
17
+ 'COMMA' => ',',
18
+ 'ELLIPSIS' => '..',
19
+ 'LEFT_BRACE' => '{',
20
+ 'LEFT_PAREN' => '(',
21
+ 'PLUS' => '+',
22
+ 'QUESTION_MARK' => '?',
23
+ 'RIGHT_BRACE' => '}',
24
+ 'RIGHT_PAREN' => ')',
25
+ 'STAR' => '*'
26
+ }.freeze
27
+ end
28
+
29
+ # Create a new AST builder instance.
30
+ # @param theTokens [Array<Rley::Lexical::Token>] The sequence of input tokens.
31
+ def initialize(theTokens)
32
+ super(theTokens)
33
+ end
34
+
35
+ protected
36
+
37
+ def terminal2node
38
+ Terminal2NodeClass
39
+ end
40
+
41
+ # Method override
42
+ def new_leaf_node(_production, _terminal, aTokenPosition, aToken)
43
+ Rley::PTree::TerminalNode.new(aToken, aTokenPosition)
44
+ end
45
+
46
+ # Factory method for creating a parent node object.
47
+ # @param aProduction [Production] Production rule
48
+ # @param aRange [Range] Range of tokens matched by the rule
49
+ # @param theTokens [Array] The input tokens
50
+ # @param theChildren [Array] Children nodes (one per rhs symbol)
51
+ def new_parent_node(aProduction, aRange, theTokens, theChildren)
52
+ mth_name = method_name(aProduction.name)
53
+ if respond_to?(mth_name, true)
54
+ node = send(mth_name, aProduction, aRange, theTokens, theChildren)
55
+ else
56
+ # Default action...
57
+ node = case aProduction.rhs.size
58
+ when 0
59
+ return_epsilon(aRange, theTokens, theChildren)
60
+ when 1
61
+ return_first_child(aRange, theTokens, theChildren)
62
+ else
63
+ node = Rley::PTree::NonTerminalNode.new(aProduction.lhs, aRange)
64
+ theChildren&.reverse_each do |child|
65
+ node.add_subnode(child) if child
66
+ end
67
+
68
+ node
69
+ end
70
+ end
71
+
72
+ node
73
+ end
74
+
75
+ # Return the AST node corresponding to the second symbol in the rhs
76
+ def reduce_to_2nd_symbol(_production, _range, _tokens, theChildren)
77
+ theChildren[1]
78
+ end
79
+
80
+ #####################################
81
+ # SEMANTIC ACTIONS
82
+ #####################################
83
+
84
+ # rule('rhs' => 'member_seq').tag 'sequence'
85
+ def reduce_sequence(_production, _range, _tokens, theChildren)
86
+ if theChildren[0].size == 1
87
+ theChildren[0].first
88
+ else
89
+ SequenceNode.new(theChildren[0].first.position, theChildren[0], nil)
90
+ end
91
+ end
92
+
93
+ # rule('member_seq' => 'member_seq member').tag 'more_members'
94
+ def reduce_more_members(_production, _range, _tokens, theChildren)
95
+ theChildren[0] << theChildren[1]
96
+ end
97
+
98
+ # rule('member_seq' => 'member')
99
+ def reduce_one_member(_production, _range, _tokens, theChildren)
100
+ [theChildren[0]]
101
+ end
102
+
103
+ # rule('strait_member' => 'base_member annotation')
104
+ def reduce_annotated_member(_production, _range, _tokens, theChildren)
105
+ theChildren[0].annotation = theChildren[1]
106
+
107
+ theChildren[0]
108
+ end
109
+
110
+ # rule('base_member' => 'SYMBOL')
111
+ def reduce_symbol(_production, _range, _tokens, theChildren)
112
+ SymbolNode.new(theChildren[0].token.position, theChildren[0].token.lexeme)
113
+ end
114
+
115
+ # rule('base_member' => 'LEFT_PAREN member_seq RIGHT_PAREN')
116
+ def reduce_grouping(_production, _range, tokens, theChildren)
117
+ if theChildren[1].size == 1
118
+ theChildren[1].first
119
+ else
120
+ rank = theChildren[0].range.high
121
+ pos = tokens[rank].position
122
+ GroupingNode.new(pos, theChildren[1], nil)
123
+ end
124
+ end
125
+
126
+ # rule('quantified_member' => 'base_member quantifier')
127
+ def reduce_quantified_member(_production, _range, _tokens, theChildren)
128
+ theChildren[0].repetition = theChildren[1]
129
+ theChildren[0]
130
+ end
131
+
132
+ # rule('quantifier' => 'QUESTION_MARK')
133
+ def reduce_question_mark(_production, _range, _tokens, _theChildren)
134
+ :zero_or_one
135
+ end
136
+
137
+ # rule('quantifier' => 'STAR')
138
+ def reduce_star(_production, _range, _tokens, _theChildren)
139
+ :zero_or_more
140
+ end
141
+
142
+ # rule('quantifier' => 'PLUS')
143
+ def reduce_plus(_production, _range, _tokens, _theChildren)
144
+ :one_or_more
145
+ end
146
+
147
+ # rule('annotation' => 'LEFT_BRACE mapping RIGHT_BRACE').tag ''
148
+ def reduce_annotation(_production, _range, _tokens, theChildren)
149
+ theChildren[1]
150
+ end
151
+
152
+ # rule('mapping' => 'mapping COMMA key_value')
153
+ def reduce_more_pairs(_production, _range, _tokens, theChildren)
154
+ hsh = theChildren[0]
155
+ hsh[theChildren[2].first] = theChildren[2].last
156
+
157
+ hsh
158
+ end
159
+
160
+ # rule('mapping' => 'key_value').tag 'one_pair'
161
+ def reduce_one_pair(_production, _range, _tokens, theChildren)
162
+ { theChildren[0].first => theChildren[0].last }
163
+ end
164
+
165
+ # rule('key_value' => 'KEY value')
166
+ def reduce_raw_pair(_production, _range, _tokens, theChildren)
167
+ key = theChildren[0].token.lexeme
168
+ value = if theChildren[1].kind_of?(Rley::PTree::TerminalNode)
169
+ theChildren[1].token.lexeme
170
+ else
171
+ theChildren[1]
172
+ end
173
+ [key, value]
174
+ end
175
+
176
+ # rule('range' => 'INT_LIT ELLIPSIS INT_LIT')
177
+ def reduce_bound_range(_production, _range, _tokens, theChildren)
178
+ low = theChildren[0].token.lexeme
179
+ high = theChildren[2].token.lexeme
180
+ case [low, high]
181
+ when ['0', '1']
182
+ :zero_or_one
183
+ when ['1', '1']
184
+ :exactly_one
185
+ else
186
+ Range.new(low.to_i, high.to_i)
187
+ end
188
+ end
189
+ end # class
190
+ end # module
191
+ end # module