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
@@ -7,23 +7,22 @@ module Rley # This module is used as a namespace
7
7
  # Abstract class. The generalization for all kinds of nodes
8
8
  # occurring in a shared packed parse forest (SPPF).
9
9
  class SPPFNode
10
-
11
- # @return [Lexical::TokenRange]
10
+ # @return [Lexical::TokenRange]
12
11
  # A range of token indices corresponding to this node.
13
12
  attr_reader(:range)
14
-
13
+
15
14
  # Constructor
16
15
  # @param aRange [Lexical::TokenRange]
17
16
  def initialize(aRange)
18
17
  @range = Lexical::TokenRange.new(aRange)
19
18
  end
20
-
21
- # Return the origin, that is, the index of the
19
+
20
+ # Return the origin, that is, the index of the
22
21
  # first token matched by this node.
23
22
  # @return [Integer]
24
- def origin()
25
- return range.low
26
- end
23
+ def origin
24
+ range.low
25
+ end
27
26
  end # class
28
27
  end # module
29
28
  end # module
@@ -25,14 +25,14 @@ module Rley # This module is used as a namespace
25
25
  # @param indentation [Integer]
26
26
  # @return [String]
27
27
  def to_string(indentation)
28
- return "#{token.terminal.name}#{range.to_string(indentation)}"
28
+ "#{token.terminal.name}#{range.to_string(indentation)}"
29
29
  end
30
-
30
+
31
31
  # Part of the 'visitee' role in Visitor design pattern.
32
32
  # @param aVisitor[ParseTreeVisitor] the visitor
33
33
  def accept(aVisitor)
34
34
  aVisitor.visit_terminal(self)
35
- end
35
+ end
36
36
  end # class
37
37
  end # module
38
38
  end # module
@@ -13,17 +13,17 @@ module Rley # This module is used as a namespace
13
13
  # Builder GoF pattern. Builder builds a complex object
14
14
  # (say, a grammar) from simpler objects (terminals and productions)
15
15
  # and using a step by step approach.
16
- class GrammarBuilder
16
+ class BaseGrammarBuilder
17
17
  # @return [Hash{String, GrmSymbol}] The mapping of grammar symbol names
18
18
  # to the matching grammar symbol object.
19
19
  attr_reader(:symbols)
20
20
 
21
- # @return [Array<Production>] The list of production rules for
21
+ # @return [Array<Production>] The list of production rules for
22
22
  # the grammar to build.
23
23
  attr_reader(:productions)
24
24
 
25
25
  # Creates a new grammar builder.
26
- # @param aBlock [Proc] code block used to build the grammar.
26
+ # @param aBlock [Proc] code block used to build the grammar.
27
27
  # @example Building a tiny English grammar
28
28
  # builder = Rley::Syntax::GrammarBuilder.new do
29
29
  # add_terminals('n', 'v', 'adj', 'det')
@@ -45,7 +45,7 @@ module Rley # This module is used as a namespace
45
45
  # @param aSymbolName [String] the name of a grammar symbol.
46
46
  # @return [GrmSymbol] the retrieved symbol object.
47
47
  def [](aSymbolName)
48
- return symbols[aSymbolName]
48
+ symbols[aSymbolName]
49
49
  end
50
50
 
51
51
  # Add the given terminal symbols to the grammar of the language
@@ -55,6 +55,14 @@ module Rley # This module is used as a namespace
55
55
  new_symbs = build_symbols(Terminal, terminalSymbols)
56
56
  symbols.merge!(new_symbs)
57
57
  end
58
+
59
+ # Add the given marker symbol to the grammar of the language
60
+ # @param aMarkerSymbol [Syntax::Marker] A mazker symbol
61
+ # @return [void]
62
+ def add_marker(aMarkerSymbol)
63
+ new_symb = build_symbol(Marker, aMarkerSymbol)
64
+ symbols[aMarkerSymbol.name] = new_symb
65
+ end
58
66
 
59
67
  # Add a production rule in the grammar given one
60
68
  # key-value pair of the form: String => Array.
@@ -67,32 +75,32 @@ module Rley # This module is used as a namespace
67
75
  # builder.rule('A' => ['a', 'A', 'c']) # 'rule' is a synonym
68
76
  # builder.rule('A' => %w[a A c]) # Use %w syntax for Array of String
69
77
  # builder.rule 'A' => %w[a A c] # Call parentheses are optional
70
- # @param aProductionRepr [Hash{String, Array<String>}]
78
+ # @param aProductionRepr [Hash{String, Array<String>}]
71
79
  # A Hash-based representation of a production.
72
80
  # @return [Production] The created Production instance
73
81
  def add_production(aProductionRepr)
74
82
  aProductionRepr.each_pair do |(lhs_name, rhs_repr)|
75
- lhs = get_nonterminal(lhs_name)
83
+ lhs = get_grm_symbol(lhs_name)
76
84
  case rhs_repr
77
85
  when Array
78
- rhs_members = rhs_repr.map { |name| get_nonterminal(name) }
86
+ rhs_members = rhs_repr.map { |name| get_grm_symbol(name) }
79
87
  when String
80
88
  rhs_lexemes = rhs_repr.scan(/\S+/)
81
- rhs_members = rhs_lexemes.map { |name| get_nonterminal(name) }
89
+ rhs_members = rhs_lexemes.map { |name| get_grm_symbol(name) }
82
90
  when Terminal
83
91
  rhs_members = [rhs_repr]
84
92
  end
85
93
  new_prod = Production.new(lhs, rhs_members)
86
94
  productions << new_prod
87
95
  end
88
-
96
+
89
97
  return productions.last
90
98
  end
91
99
 
92
100
  # Given the grammar symbols and productions added to the builder,
93
101
  # build the resulting grammar (if not yet done).
94
- # @return [Grammar] the created grammar object.
95
- def grammar()
102
+ # @return [Grammar] the created grammar object.
103
+ def grammar
96
104
  unless @grammar
97
105
  raise StandardError, 'No symbol found for grammar' if symbols.empty?
98
106
  if productions.empty?
@@ -113,7 +121,7 @@ module Rley # This module is used as a namespace
113
121
  unused = all_terminals.reject { |a_term| in_use.include?(a_term) }
114
122
  unless unused.empty?
115
123
  suffix = "#{unused.map(&:name).join(', ')}."
116
- raise StandardError, 'Useless terminal symbol(s): ' + suffix
124
+ raise StandardError, "Useless terminal symbol(s): #{suffix}"
117
125
  end
118
126
 
119
127
  @grammar = Grammar.new(productions.dup)
@@ -122,6 +130,20 @@ module Rley # This module is used as a namespace
122
130
  return @grammar
123
131
  end
124
132
 
133
+ # When a symbol, say symb, in a rhs is followed by a '+' modifier,
134
+ # then a rule will be generated with a lhs named symb + suffix_plus
135
+ def suffix_plus
136
+ '_plus'
137
+ end
138
+
139
+ def suffix_plus_more
140
+ 'base_plus_more'
141
+ end
142
+
143
+ def suffix_plus_last
144
+ 'base_plus_last'
145
+ end
146
+
125
147
  alias rule add_production
126
148
 
127
149
  private
@@ -149,24 +171,40 @@ module Rley # This module is used as a namespace
149
171
  # @param aSymbolArg [GrmSymbol-like or String]
150
172
  # @return [Array] list of grammar symbols
151
173
  def build_symbol(aClass, aSymbolArg)
152
- a_symbol = if aSymbolArg.kind_of?(GrmSymbol)
153
- aSymbolArg
154
- else
155
- aClass.new(aSymbolArg)
156
- end
157
-
158
- return a_symbol
174
+ if aSymbolArg.kind_of?(GrmSymbol)
175
+ aSymbolArg
176
+ else
177
+ aClass.new(aSymbolArg)
178
+ end
159
179
  end
160
180
 
161
181
  # Retrieve the non-terminal symbol with given name.
162
182
  # If it doesn't exist yet, then it is created on the fly.
163
183
  # @param aSymbolName [String] the name of the grammar symbol to retrieve
164
184
  # @return [NonTerminal]
165
- def get_nonterminal(aSymbolName)
166
- unless symbols.include? aSymbolName
167
- symbols[aSymbolName] = NonTerminal.new(aSymbolName)
185
+ def get_grm_symbol(aSymbolName)
186
+ unless aSymbolName.end_with?('+') && aSymbolName.length > 1
187
+ name = aSymbolName
188
+ else
189
+ name = aSymbolName.chop
190
+ case aSymbolName[-1]
191
+ when '+'
192
+ name_modified = "#{name}#{suffix_plus}"
193
+ unless symbols.include? name_modified
194
+ symbols[name_modified] = NonTerminal.new(name_modified)
195
+ rule(name_modified => [name_modified, name]).as suffix_plus_more
196
+ rule(name_modified => name).as suffix_plus_last
197
+ end
198
+ name = name_modified
199
+ else
200
+ err_msg = "Unknown symbol modifier #{aSymbolName[-1]}"
201
+ raise NotImplementedError, err_msg
202
+ end
168
203
  end
169
- return symbols[aSymbolName]
204
+
205
+ symbols[name] = NonTerminal.new(name) unless symbols.include? name
206
+
207
+ symbols[name]
170
208
  end
171
209
  end # class
172
210
  end # module
@@ -48,13 +48,13 @@ module Rley # This module is used as a namespace
48
48
  end
49
49
 
50
50
  # @return [Array] The list of non-terminals in the grammar.
51
- def non_terminals()
51
+ def non_terminals
52
52
  @non_terminals ||= symbols.select { |s| s.kind_of?(NonTerminal) }
53
53
  end
54
54
 
55
55
  # @return [Production] The start production of the grammar (i.e.
56
56
  # the rule that specifies the syntax for the start symbol.
57
- def start_production()
57
+ def start_production
58
58
  return rules[0]
59
59
  end
60
60
 
@@ -99,7 +99,7 @@ module Rley # This module is used as a namespace
99
99
  end
100
100
 
101
101
  # Perform some check of the grammar.
102
- def diagnose()
102
+ def diagnose
103
103
  mark_undefined
104
104
  mark_generative
105
105
  compute_nullable
@@ -193,7 +193,7 @@ module Rley # This module is used as a namespace
193
193
 
194
194
  # For each non-terminal determine whether it is nullable or not.
195
195
  # A nullable nonterminal is a nonterminal that can match an empty string.
196
- def compute_nullable()
196
+ def compute_nullable
197
197
  non_terminals.each { |nterm| nterm.nullable = false }
198
198
  nullable_sets = [direct_nullable]
199
199
 
@@ -236,7 +236,7 @@ module Rley # This module is used as a namespace
236
236
  nullables << prod.lhs
237
237
  end
238
238
 
239
- return nullables
239
+ nullables
240
240
  end
241
241
 
242
242
  # For each prodction determine whether it is nullable or not.
@@ -5,7 +5,7 @@ module Rley # This module is used as a namespace
5
5
  # Abstract class for grammar symbols.
6
6
  # A grammar symbol is an element that appears in grammar rules.
7
7
  class GrmSymbol
8
- # The name of the grammar symbol
8
+ # @return [String] The name of the grammar symbol
9
9
  attr_reader(:name)
10
10
 
11
11
  # An indicator that tells whether the grammar symbol can generate a
@@ -23,19 +23,19 @@ module Rley # This module is used as a namespace
23
23
 
24
24
  # The String representation of the grammar symbol
25
25
  # @return [String]
26
- def to_s()
27
- return name.to_s
26
+ def to_s
27
+ name.to_s
28
28
  end
29
29
 
30
30
  # @return [Boolean] true iff the symbol is a terminal
31
- def terminal?()
31
+ def terminal?
32
32
  # Default implementation to override if necessary
33
- return false
33
+ false
34
34
  end
35
35
 
36
36
  # @return [Boolean] true iff the symbol is generative.
37
- def generative?()
38
- return @generative
37
+ def generative?
38
+ @generative
39
39
  end
40
40
  end # class
41
41
  end # module
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rley # This module is used as a namespace
4
+ module Syntax # This module is used as a namespace
5
+ # A constraint that indicates that a given rhs member must
6
+ # match the closest given terminal symbol in that rhs
7
+ class MatchClosest
8
+ # @return [Integer] index of constrained symbol to match
9
+ attr_reader(:idx_symbol)
10
+
11
+ # @return [String] name of closest preceding symbol to pair
12
+ attr_reader(:closest_symb)
13
+
14
+ # @return [NilClass, Array<Parser::ParseEntry>] set of entries with closest symbol
15
+ attr_accessor(:entries)
16
+
17
+ # @param aSymbolSeq [Rley::Syntax::SymbolSeq] a sequence of grammar symbols
18
+ # @param idxSymbol [Integer] index of symbol
19
+ # @param nameClosest [String] Terminal symbol name
20
+ def initialize(aSymbolSeq, idxSymbol, nameClosest)
21
+ @idx_symbol = valid_idx_symbol(idxSymbol, aSymbolSeq)
22
+ @closest_symb = valid_name_closest(nameClosest)
23
+ end
24
+
25
+ private
26
+
27
+ # Check that the provided index is within plausible bounds
28
+ def valid_idx_symbol(idxSymbol, aSymbolSeq)
29
+ bounds = 0 .. aSymbolSeq.size - 1
30
+ err_msg_outbound = 'Index of symbol out of bound'
31
+ raise StandardError, err_msg_outbound unless bounds.include? idxSymbol
32
+
33
+ idxSymbol
34
+ end
35
+
36
+ def valid_name_closest(nameClosest)
37
+ nameClosest
38
+ end
39
+ end # class
40
+ end # module
41
+ end # module
42
+
43
+ # End of file
@@ -9,41 +9,35 @@ module Rley # This module is used as a namespace
9
9
  class NonTerminal < GrmSymbol
10
10
  # A non-terminal symbol is nullable if it can match an empty string.
11
11
  attr_writer(:nullable)
12
-
12
+
13
13
  # A non-terminal symbol is undefined if no production rule in the grammar
14
14
  # has that non-terminal symbol in its left-hand side.
15
15
  attr_writer(:undefined)
16
-
17
- # A non-terminal symbol is unreachable if it cannot be reached (derived)
16
+
17
+ # A non-terminal symbol is unreachable if it cannot be reached (derived)
18
18
  # from the start symbol.
19
19
  attr_writer(:unreachable)
20
20
 
21
- # Constructor.
22
- # @param aName [String] The name of the grammar symbol.
23
- def initialize(aName)
24
- super(aName)
25
- end
26
-
27
21
  # @return [false/true] Return true if the symbol derives
28
22
  # the empty string. As non-terminal symbol is nullable when it can
29
23
  # can match to zero input token.
30
24
  # The "nullability" of a non-terminal can practically be determined once
31
25
  # all the production rules of the grammar are specified.
32
- def nullable?()
26
+ def nullable?
33
27
  return @nullable
34
28
  end
35
-
29
+
36
30
  # @return [false/true] Return true if the symbol doesn't appear
37
31
  # on the left-hand side of any production rule.
38
- def undefined?()
32
+ def undefined?
39
33
  return @undefined
40
34
  end
41
-
35
+
42
36
  # @return [false/true] Return true if the symbol cannot be derived
43
37
  # from the start symbol.
44
- def unreachable?()
38
+ def unreachable?
45
39
  return @unreachable
46
- end
40
+ end
47
41
  end # class
48
42
  end # module
49
43
  end # module
@@ -31,6 +31,9 @@ module Rley # This module is used as a namespace
31
31
  # rhs members are nullable.
32
32
  attr_writer(:nullable)
33
33
 
34
+ # @return [Array<Syntax::MatchClosest>] A list of constraints between rhs members
35
+ attr_accessor(:constraints)
36
+
34
37
  # Provide common alternate names to lhs and rhs accessors
35
38
 
36
39
  alias body rhs
@@ -42,37 +45,38 @@ module Rley # This module is used as a namespace
42
45
  def initialize(aNonTerminal, theSymbols)
43
46
  @lhs = valid_lhs(aNonTerminal)
44
47
  @rhs = valid_rhs(theSymbols)
48
+ @constraints = []
45
49
  end
46
50
 
47
51
  # Is the rhs empty?
48
52
  # @return [Boolean] true if the rhs has no members.
49
- def empty?()
50
- return rhs.empty?
53
+ def empty?
54
+ rhs.empty?
51
55
  end
52
56
 
53
57
  # Return true iff the production is generative
54
- def generative?()
55
- if @generative.nil?
56
- end
58
+ def generative?
59
+ # if @generative.nil?
60
+ # end
57
61
 
58
- return @generative
62
+ @generative
59
63
  end
60
64
 
61
65
  # @return [Boolen] true iff the production is nullable
62
- def nullable?()
63
- return @nullable
66
+ def nullable?
67
+ @nullable
64
68
  end
65
69
 
66
70
  # Returns a string containing a human-readable representation of the
67
71
  # production.
68
72
  # @return [String]
69
- def inspect()
73
+ def inspect
70
74
  result = +"#<#{self.class.name}:#{object_id}"
71
75
  result << " @name=\"#{name}\""
72
76
  result << " @lhs=#{lhs.name}"
73
77
  result << " @rhs=#{rhs.inspect}"
74
78
  result << " @generative=#{@generative}>"
75
- return result
79
+ result
76
80
  end
77
81
 
78
82
  # A setter for the production name
@@ -81,6 +85,8 @@ module Rley # This module is used as a namespace
81
85
  @name = aName
82
86
  end
83
87
 
88
+ alias tag as
89
+
84
90
  private
85
91
 
86
92
  # Validation method. Return the validated input argument or