rley 0.8.14 → 0.9.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +20 -2
- data/CHANGELOG.md +14 -0
- data/Gemfile +8 -0
- data/examples/general/calc_iter1/spec/calculator_spec.rb +9 -9
- data/examples/general/calc_iter2/spec/calculator_spec.rb +39 -39
- data/examples/general/recursive_right.rb +2 -2
- data/lib/rley/constants.rb +2 -2
- data/lib/rley/engine.rb +3 -1
- data/lib/rley/formatter/asciitree.rb +4 -1
- data/lib/rley/gfg/epsilon_edge.rb +0 -2
- data/lib/rley/gfg/grm_flow_graph.rb +7 -9
- data/lib/rley/gfg/item_vertex.rb +1 -1
- data/lib/rley/gfg/vertex.rb +11 -0
- data/lib/rley/lexical/token.rb +10 -3
- data/lib/rley/parse_forest_visitor.rb +3 -3
- data/lib/rley/parse_rep/ast_base_builder.rb +6 -5
- data/lib/rley/parse_rep/parse_forest_builder.rb +4 -2
- data/lib/rley/parse_rep/parse_tree_builder.rb +14 -2
- data/lib/rley/parse_rep/parse_tree_factory.rb +1 -1
- data/lib/rley/parser/error_reason.rb +2 -2
- data/lib/rley/parser/gfg_chart.rb +2 -2
- data/lib/rley/parser/gfg_earley_parser.rb +2 -2
- data/lib/rley/parser/gfg_parsing.rb +1 -1
- data/lib/rley/parser/parse_entry.rb +4 -4
- data/lib/rley/parser/parse_entry_set.rb +4 -2
- data/lib/rley/parser/parse_entry_tracker.rb +10 -7
- data/lib/rley/parser/parse_walker_factory.rb +9 -8
- data/lib/rley/ptree/parse_tree_node.rb +6 -0
- data/lib/rley/ptree/terminal_node.rb +1 -1
- data/lib/rley/rgn/ast_builder.rb +2 -2
- data/lib/rley/rgn/ast_node.rb +11 -1
- data/lib/rley/rgn/ast_visitor.rb +2 -2
- data/lib/rley/rgn/composite_node.rb +1 -1
- data/lib/rley/rgn/grammar_builder.rb +12 -14
- data/lib/rley/rgn/parser.rb +2 -2
- data/lib/rley/rgn/tokenizer.rb +1 -1
- data/lib/rley/rley_error.rb +0 -4
- data/lib/rley/sppf/composite_node.rb +6 -0
- data/lib/rley/sppf/parse_forest.rb +7 -7
- data/lib/rley/sppf/sppf_node.rb +15 -1
- data/lib/rley/syntax/base_grammar_builder.rb +3 -12
- data/lib/rley/syntax/grammar.rb +9 -4
- data/lib/rley/syntax/production.rb +1 -1
- data/spec/rley/base/dotted_item_spec.rb +46 -46
- data/spec/rley/base/grm_items_builder_spec.rb +1 -1
- data/spec/rley/engine_spec.rb +50 -50
- data/spec/rley/formatter/asciitree_spec.rb +8 -8
- data/spec/rley/formatter/bracket_notation_spec.rb +10 -10
- data/spec/rley/formatter/debug_spec.rb +10 -10
- data/spec/rley/formatter/json_spec.rb +6 -7
- data/spec/rley/gfg/call_edge_spec.rb +6 -6
- data/spec/rley/gfg/edge_spec.rb +8 -7
- data/spec/rley/gfg/end_vertex_spec.rb +8 -7
- data/spec/rley/gfg/epsilon_edge_spec.rb +5 -4
- data/spec/rley/gfg/grm_flow_graph_spec.rb +33 -34
- data/spec/rley/gfg/item_vertex_spec.rb +34 -36
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +12 -12
- data/spec/rley/gfg/return_edge_spec.rb +6 -6
- data/spec/rley/gfg/scan_edge_spec.rb +7 -6
- data/spec/rley/gfg/shortcut_edge_spec.rb +15 -15
- data/spec/rley/gfg/start_vertex_spec.rb +8 -8
- data/spec/rley/gfg/vertex_spec.rb +18 -18
- data/spec/rley/lexical/literal_spec.rb +5 -5
- data/spec/rley/lexical/token_range_spec.rb +55 -55
- data/spec/rley/lexical/token_spec.rb +17 -16
- data/spec/rley/parse_forest_visitor_spec.rb +30 -32
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +2 -2
- data/spec/rley/parse_rep/ast_builder_spec.rb +30 -30
- data/spec/rley/parse_rep/cst_builder_spec.rb +85 -85
- data/spec/rley/parse_rep/groucho_spec.rb +23 -23
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +42 -42
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +10 -12
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +10 -15
- data/spec/rley/parse_tree_visitor_spec.rb +43 -46
- data/spec/rley/parser/dangling_else_spec.rb +12 -12
- data/spec/rley/parser/error_reason_spec.rb +37 -37
- data/spec/rley/parser/gfg_chart_spec.rb +27 -29
- data/spec/rley/parser/gfg_earley_parser_spec.rb +55 -56
- data/spec/rley/parser/gfg_parsing_spec.rb +106 -103
- data/spec/rley/parser/parse_entry_set_spec.rb +63 -61
- data/spec/rley/parser/parse_entry_spec.rb +73 -71
- data/spec/rley/parser/parse_walker_factory_spec.rb +14 -15
- data/spec/rley/ptree/non_terminal_node_spec.rb +16 -16
- data/spec/rley/ptree/parse_tree_node_spec.rb +11 -11
- data/spec/rley/ptree/parse_tree_spec.rb +6 -8
- data/spec/rley/ptree/terminal_node_spec.rb +6 -6
- data/spec/rley/rgn/grammar_builder_spec.rb +69 -67
- data/spec/rley/rgn/parser_spec.rb +63 -63
- data/spec/rley/rgn/repetition_node_spec.rb +15 -15
- data/spec/rley/rgn/sequence_node_spec.rb +10 -10
- data/spec/rley/rgn/symbol_node_spec.rb +5 -6
- data/spec/rley/rgn/tokenizer_spec.rb +68 -67
- data/spec/rley/sppf/alternative_node_spec.rb +16 -16
- data/spec/rley/sppf/non_terminal_node_spec.rb +20 -20
- data/spec/rley/sppf/token_node_spec.rb +13 -13
- data/spec/rley/syntax/base_grammar_builder_spec.rb +76 -86
- data/spec/rley/syntax/grammar_spec.rb +40 -78
- data/spec/rley/syntax/grm_symbol_spec.rb +7 -7
- data/spec/rley/syntax/match_closest_spec.rb +8 -8
- data/spec/rley/syntax/non_terminal_spec.rb +25 -25
- data/spec/rley/syntax/production_spec.rb +33 -33
- data/spec/rley/syntax/symbol_seq_spec.rb +27 -27
- data/spec/rley/syntax/terminal_spec.rb +12 -11
- data/spec/support/base_tokenizer_spec.rb +9 -8
- metadata +8 -25
@@ -148,7 +148,7 @@ module Rley # This module is used as a namespace
|
|
148
148
|
# ... without changing current path
|
149
149
|
create_epsilon_node(anEntry, anIndex)
|
150
150
|
end
|
151
|
-
curr_path.pop if curr_parent.
|
151
|
+
curr_path.pop if curr_parent.is_a?(SPPF::AlternativeNode)
|
152
152
|
end
|
153
153
|
|
154
154
|
when :backtrack
|
@@ -172,7 +172,7 @@ module Rley # This module is used as a namespace
|
|
172
172
|
# ... without changing current path
|
173
173
|
create_epsilon_node(anEntry, anIndex)
|
174
174
|
end
|
175
|
-
curr_path.pop if curr_parent.
|
175
|
+
curr_path.pop if curr_parent.is_a?(SPPF::AlternativeNode)
|
176
176
|
end
|
177
177
|
end
|
178
178
|
end
|
@@ -221,6 +221,8 @@ module Rley # This module is used as a namespace
|
|
221
221
|
|
222
222
|
def create_epsilon_node(anEntry, anIndex)
|
223
223
|
new_node = SPPF::EpsilonNode.new(anIndex)
|
224
|
+
|
225
|
+
# @type var candidate : SPPF::EpsilonNode
|
224
226
|
candidate = add_node_to_forest(new_node)
|
225
227
|
entry2node[anEntry] = candidate
|
226
228
|
|
@@ -19,6 +19,7 @@ module Rley # This module is used as a namespace
|
|
19
19
|
# @param aSymbol [Syntax::Symbol] A symbol from grammar.
|
20
20
|
def initialize(aRange, aSymbol)
|
21
21
|
super
|
22
|
+
# @type self:CSTRawNode
|
22
23
|
self.range = aRange
|
23
24
|
self.symbol = aSymbol
|
24
25
|
self.children = nil
|
@@ -77,7 +78,7 @@ module Rley # This module is used as a namespace
|
|
77
78
|
|
78
79
|
protected
|
79
80
|
|
80
|
-
# Return the stack
|
81
|
+
# Return the stack of CSTRawNode
|
81
82
|
attr_reader(:stack)
|
82
83
|
|
83
84
|
# Overriding method.
|
@@ -180,6 +181,7 @@ module Rley # This module is used as a namespace
|
|
180
181
|
# For debugging purposes
|
181
182
|
raise StandardError if previous_tos.symbol != non_terminal
|
182
183
|
|
184
|
+
# @type var previous_tos : CSTRawNode
|
183
185
|
new_node = new_parent_node(rule, previous_tos.range,
|
184
186
|
tokens, previous_tos.children)
|
185
187
|
if stack.empty?
|
@@ -207,7 +209,9 @@ module Rley # This module is used as a namespace
|
|
207
209
|
# @param anEntry [ParseEntry] The entry being visited
|
208
210
|
def terminal_before_dot?(anEntry)
|
209
211
|
prev_symbol = anEntry.prev_symbol
|
210
|
-
|
212
|
+
|
213
|
+
# @type var prev_symbol : Syntax::GrmSymbol
|
214
|
+
prev_symbol.terminal?
|
211
215
|
end
|
212
216
|
|
213
217
|
# A terminal symbol was detected at left of dot.
|
@@ -262,6 +266,14 @@ module Rley # This module is used as a namespace
|
|
262
266
|
|
263
267
|
non_terminal
|
264
268
|
end
|
269
|
+
|
270
|
+
def new_leaf_node(_aProduction, _aTerminal, _aTokenPosition, _aToken)
|
271
|
+
raise NotImplementedError
|
272
|
+
end
|
273
|
+
|
274
|
+
def new_parent_node(_aProduction, _aRange, _theTokens, _theChildren)
|
275
|
+
raise NotImplementedError
|
276
|
+
end
|
265
277
|
end # class
|
266
278
|
end # module
|
267
279
|
end # module
|
@@ -15,7 +15,7 @@ module Rley # This module is used as a namespace
|
|
15
15
|
# that will create piece by piece the forest
|
16
16
|
def builder(aParseResult, aBuilder = nil)
|
17
17
|
if aBuilder
|
18
|
-
aBuilder.new(aParseResult.tokens)
|
18
|
+
aBuilder.new(aParseResult.tokens) # steep:ignore UnexpectedPositionalArgument
|
19
19
|
else
|
20
20
|
CSTBuilder.new(aParseResult.tokens)
|
21
21
|
end
|
@@ -7,11 +7,11 @@ module Rley # Module used as a namespace
|
|
7
7
|
# detected by Rley.
|
8
8
|
class ErrorReason
|
9
9
|
# @!attribute [r] rank
|
10
|
-
# @return [
|
10
|
+
# @return [Integer] The rank number of the offending input token
|
11
11
|
attr_reader(:rank)
|
12
12
|
|
13
13
|
# Constructor
|
14
|
-
# @param aRank [
|
14
|
+
# @param aRank [Integer] The sequence number of the offending input token.
|
15
15
|
def initialize(aRank)
|
16
16
|
@rank = aRank
|
17
17
|
end
|
@@ -98,7 +98,7 @@ module Rley # This module is used as a namespace
|
|
98
98
|
new_entry = ParseEntry.new(aVertex, anOrigin)
|
99
99
|
result = self[anIndex].push_entry(new_entry)
|
100
100
|
|
101
|
-
if aVertex.
|
101
|
+
if aVertex.is_a?(GFG::ItemVertex) && aVertex.dotted_item.constraint
|
102
102
|
ct = aVertex.dotted_item.constraint
|
103
103
|
|
104
104
|
case ct
|
@@ -198,8 +198,8 @@ module Rley # This module is used as a namespace
|
|
198
198
|
private
|
199
199
|
|
200
200
|
def add_entry_set
|
201
|
-
@sets << ParseEntrySet.new
|
202
201
|
@constraints << []
|
202
|
+
@sets << ParseEntrySet.new
|
203
203
|
end
|
204
204
|
|
205
205
|
def update_match_closest(aConstraint, anIndex)
|
@@ -32,7 +32,7 @@ module Rley # This module is used as a namespace
|
|
32
32
|
|
33
33
|
aTokenSequence.each_with_index do |token, i|
|
34
34
|
parse_for_token(result, i)
|
35
|
-
if token.terminal.
|
35
|
+
if token.terminal.is_a?(String)
|
36
36
|
symb = grammar.name2symbol[token.terminal]
|
37
37
|
token.instance_variable_set(:@terminal, symb)
|
38
38
|
end
|
@@ -51,7 +51,7 @@ module Rley # This module is used as a namespace
|
|
51
51
|
result.chart[index].each do |entry|
|
52
52
|
# Is entry of the form? [A => alpha . B beta, k]...
|
53
53
|
next_symbol = entry.next_symbol
|
54
|
-
if next_symbol.
|
54
|
+
if next_symbol.is_a?(Syntax::NonTerminal)
|
55
55
|
# ...apply the Call rule
|
56
56
|
call_rule(result, entry, index)
|
57
57
|
end
|
@@ -338,7 +338,7 @@ module Rley # This module is used as a namespace
|
|
338
338
|
full_range = { low: 0, high: anIndex }
|
339
339
|
start_production = chart.start_dotted_rule.production
|
340
340
|
|
341
|
-
ParseForestBuilder.new(start_production, full_range)
|
341
|
+
ParseRep::ParseForestBuilder.new(start_production, full_range)
|
342
342
|
end
|
343
343
|
|
344
344
|
# Factory method. Creates and initializes a ParseEntryTracker instance.
|
@@ -62,13 +62,13 @@ module Rley # This module is used as a namespace
|
|
62
62
|
|
63
63
|
# Returns true iff the vertex is a start vertex (i.e. of the form: .X)
|
64
64
|
def start_entry?
|
65
|
-
vertex.
|
65
|
+
vertex.is_a?(GFG::StartVertex)
|
66
66
|
end
|
67
67
|
|
68
68
|
# Returns true iff the vertex is at the start of rhs
|
69
69
|
# (i.e. of the form: X => .Y
|
70
70
|
def entry_entry?
|
71
|
-
return false unless vertex.
|
71
|
+
return false unless vertex.is_a?(GFG::ItemVertex)
|
72
72
|
|
73
73
|
vertex.dotted_item.at_start?
|
74
74
|
end
|
@@ -76,7 +76,7 @@ module Rley # This module is used as a namespace
|
|
76
76
|
# Returns true iff the vertex corresponds to a dotted item
|
77
77
|
# X => Y
|
78
78
|
def dotted_entry?
|
79
|
-
vertex.
|
79
|
+
vertex.is_a?(GFG::ItemVertex)
|
80
80
|
end
|
81
81
|
|
82
82
|
# Returns true iff the vertex is at end of rhs (i.e. of the form: X => Y.)
|
@@ -86,7 +86,7 @@ module Rley # This module is used as a namespace
|
|
86
86
|
|
87
87
|
# Returns true iff the vertex is an end vertex (i.e. of the form: X.)
|
88
88
|
def end_entry?
|
89
|
-
vertex.
|
89
|
+
vertex.is_a?(GFG::EndVertex)
|
90
90
|
end
|
91
91
|
|
92
92
|
# Return the symbol before the dot (if any)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'forwardable' # For the Delegation pattern
|
4
|
-
require 'set'
|
5
4
|
|
6
5
|
require_relative '../syntax/terminal'
|
7
6
|
require_relative '../syntax/non_terminal'
|
@@ -63,6 +62,7 @@ module Rley # This module is used as a namespace
|
|
63
62
|
# @return [ParseEntry] the passed parse entry if it pushes it
|
64
63
|
def push_entry(anEntry)
|
65
64
|
entry_key = anEntry.hash
|
65
|
+
# @type var result : ParseEntry | false
|
66
66
|
result = membership.fetch(entry_key, false)
|
67
67
|
unless result
|
68
68
|
@entries << anEntry
|
@@ -72,6 +72,7 @@ module Rley # This module is used as a namespace
|
|
72
72
|
result = anEntry
|
73
73
|
end
|
74
74
|
|
75
|
+
# @type var result : ParseEntry
|
75
76
|
result
|
76
77
|
end
|
77
78
|
|
@@ -112,9 +113,10 @@ module Rley # This module is used as a namespace
|
|
112
113
|
|
113
114
|
def add_lookup4symbol(anEntry)
|
114
115
|
symb = anEntry.next_symbol
|
115
|
-
if symb.
|
116
|
+
if symb.is_a?(Syntax::Terminal)
|
116
117
|
@entries4term[symb] << anEntry
|
117
118
|
else
|
119
|
+
# @type var symb : Syntax::NonTerminal
|
118
120
|
@entries4n_term[symb] << anEntry
|
119
121
|
end
|
120
122
|
end
|
@@ -21,31 +21,34 @@ module Rley # This module is used as a namespace
|
|
21
21
|
|
22
22
|
# Write accessor. Sets the value of the entry set index
|
23
23
|
def entry_set_index=(anIndex)
|
24
|
-
@entry_set_index = anIndex
|
25
24
|
@processed_entries = {}
|
25
|
+
@entry_set_index = anIndex
|
26
26
|
end
|
27
27
|
|
28
28
|
# Write accessor. Set the given parse entry as the current one.
|
29
29
|
def parse_entry=(aParseEntry)
|
30
30
|
raise StandardError, 'Nil parse entry' if aParseEntry.nil?
|
31
31
|
|
32
|
-
@parse_entry
|
32
|
+
# @type var parse_entry : Rley::Parser::ParseEntry
|
33
33
|
processed_entries[parse_entry] = true
|
34
|
+
@parse_entry = aParseEntry
|
34
35
|
end
|
35
36
|
|
36
37
|
# Take the first provided entry that wasn't processed yet.
|
37
|
-
def select_entry(
|
38
|
-
a_entry =
|
39
|
-
self.parse_entry = a_entry
|
38
|
+
def select_entry(entries)
|
39
|
+
a_entry = entries.find { |st| !processed_entries.include?(st) }
|
40
|
+
self.parse_entry = a_entry # steep:ignore
|
40
41
|
end
|
41
42
|
|
42
43
|
# The dotted item for the current parse entry.
|
44
|
+
# @return [Rley::Base::DottedItem, nil]
|
43
45
|
def curr_dotted_item
|
44
|
-
parse_entry.
|
46
|
+
parse_entry&.vertex.dotted_item # steep:ignore
|
45
47
|
end
|
46
48
|
|
49
|
+
# @return [Syntax::GrmSymbol, nil] Return the symbol before the dot
|
47
50
|
def symbol_on_left
|
48
|
-
curr_dotted_item
|
51
|
+
curr_dotted_item&.prev_symbol
|
49
52
|
end
|
50
53
|
|
51
54
|
# Notification that one begins with the previous entry set
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
3
|
require_relative '../gfg/call_edge'
|
5
4
|
require_relative '../gfg/scan_edge'
|
6
5
|
require_relative '../gfg/epsilon_edge'
|
@@ -119,8 +118,9 @@ module Rley # This module is used as a namespace
|
|
119
118
|
# rubocop: disable Lint/DuplicateBranch
|
120
119
|
def visit_entry(anEntry, aContext)
|
121
120
|
index = aContext.entry_set_index
|
122
|
-
aContext.nterm2start[[anEntry, index]] if anEntry.start_entry?
|
121
|
+
aContext.nterm2start[[anEntry, index]] if anEntry.start_entry? # steep:ignore
|
123
122
|
|
123
|
+
# @type var event : [Symbol, ParseEntry, Integer]
|
124
124
|
if aContext.visitees.include?(anEntry) # Already visited?...
|
125
125
|
case anEntry.vertex
|
126
126
|
when GFG::EndVertex
|
@@ -156,8 +156,8 @@ module Rley # This module is used as a namespace
|
|
156
156
|
end
|
157
157
|
# rubocop: enable Lint/DuplicateBranch
|
158
158
|
|
159
|
-
def detect_scan_edge(
|
160
|
-
nil unless
|
159
|
+
def detect_scan_edge(ctx)
|
160
|
+
nil unless ctx.curr_entry.dotted_entry?
|
161
161
|
end
|
162
162
|
|
163
163
|
# Given the current entry from context object
|
@@ -179,22 +179,22 @@ module Rley # This module is used as a namespace
|
|
179
179
|
new_entry = aContext.curr_entry.antecedents.first
|
180
180
|
events = [new_entry]
|
181
181
|
traversed_edge = new_entry.vertex.edges.first
|
182
|
-
if new_entry.vertex.
|
182
|
+
if new_entry.vertex.is_a?(GFG::EndVertex)
|
183
183
|
# Return edge encountered
|
184
184
|
# Push current entry onto stack
|
185
185
|
# puts "Push on return stack #{aContext.curr_entry}"
|
186
186
|
aContext.return_stack << aContext.curr_entry
|
187
|
-
elsif traversed_edge.
|
187
|
+
elsif traversed_edge.is_a?(GFG::CallEdge)
|
188
188
|
# Pop top of stack
|
189
189
|
err_msg = 'Return stack empty!'
|
190
190
|
raise ScriptError, err_msg if aContext.return_stack.empty?
|
191
191
|
|
192
192
|
aContext.return_stack.pop
|
193
193
|
# puts "Pop from return stack matching entry #{new_entry}"
|
194
|
-
elsif traversed_edge.
|
194
|
+
elsif traversed_edge.is_a?(GFG::ScanEdge)
|
195
195
|
# Scan edge encountered, decrease sigma set index
|
196
196
|
aContext.entry_set_index -= 1
|
197
|
-
elsif traversed_edge.
|
197
|
+
elsif traversed_edge.is_a?(GFG::EpsilonEdge)
|
198
198
|
# Do nothing
|
199
199
|
else
|
200
200
|
raise NotImplementedError, "edge is a #{traversed_edge.class}"
|
@@ -270,6 +270,7 @@ module Rley # This module is used as a namespace
|
|
270
270
|
raise ScriptError, 'Empty return stack' if aContext.return_stack.empty?
|
271
271
|
|
272
272
|
# Retrieve top of stack
|
273
|
+
# @type var tos : Rley::Parser::ParseEntry
|
273
274
|
tos = aContext.return_stack.pop
|
274
275
|
tos_dotted_item = tos.vertex.dotted_item
|
275
276
|
|
@@ -37,6 +37,12 @@ module Rley # This module is used as a namespace
|
|
37
37
|
def to_s
|
38
38
|
"#{symbol.name}#{range.to_string(0)}"
|
39
39
|
end
|
40
|
+
|
41
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
42
|
+
# @param aVisitor[ParseTreeVisitor] the visitor
|
43
|
+
def accept(aVisitor)
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
40
46
|
end # class
|
41
47
|
end # module
|
42
48
|
end # module
|
@@ -14,7 +14,7 @@ module Rley # This module is used as a namespace
|
|
14
14
|
# (major, minor) =
|
15
15
|
|
16
16
|
# Use '1.class' trick to support both Integer and Fixnum classes
|
17
|
-
range = aPos.
|
17
|
+
range = aPos.is_a?(1.class) ? { low: aPos, high: aPos + 1 } : aPos
|
18
18
|
super(aToken.terminal, range)
|
19
19
|
@token = aToken
|
20
20
|
end
|
data/lib/rley/rgn/ast_builder.rb
CHANGED
@@ -29,7 +29,7 @@ module Rley
|
|
29
29
|
protected
|
30
30
|
|
31
31
|
def terminal2node
|
32
|
-
Terminal2NodeClass
|
32
|
+
Terminal2NodeClass # steep:ignore UnknownConstant
|
33
33
|
end
|
34
34
|
|
35
35
|
# Method override
|
@@ -166,7 +166,7 @@ module Rley
|
|
166
166
|
# rule('key_value' => 'KEY value')
|
167
167
|
def reduce_raw_pair(_production, _range, _tokens, theChildren)
|
168
168
|
key = theChildren[0].token.lexeme
|
169
|
-
value = if theChildren[1].
|
169
|
+
value = if theChildren[1].is_a?(Rley::PTree::TerminalNode)
|
170
170
|
theChildren[1].token.lexeme
|
171
171
|
else
|
172
172
|
theChildren[1]
|
data/lib/rley/rgn/ast_node.rb
CHANGED
@@ -22,7 +22,7 @@ module Rley
|
|
22
22
|
def annotation_to_text
|
23
23
|
map_arr = []
|
24
24
|
@annotation.each_pair do |key, val|
|
25
|
-
literal = val.
|
25
|
+
literal = val.is_a?(String) ? "'#{val}'" : val
|
26
26
|
map_arr << "#{key}: #{literal}"
|
27
27
|
end
|
28
28
|
|
@@ -34,6 +34,16 @@ module Rley
|
|
34
34
|
# Default: do nothing ...
|
35
35
|
end
|
36
36
|
|
37
|
+
# @nodoc
|
38
|
+
def name
|
39
|
+
raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
# @nodoc
|
43
|
+
def to_text
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
|
37
47
|
# Abstract method (must be overriden in subclasses).
|
38
48
|
# Part of the 'visitee' role in Visitor design pattern.
|
39
49
|
# @param _visitor [ASTVisitor] the visitor
|
data/lib/rley/rgn/ast_visitor.rb
CHANGED
@@ -75,7 +75,7 @@ module Rley
|
|
75
75
|
|
76
76
|
# Visit event. The visitor is about to visit the subnodes of a non
|
77
77
|
# terminal node.
|
78
|
-
# @param aParentNode [
|
78
|
+
# @param aParentNode [CompositeNode] the parent node.
|
79
79
|
def traverse_subnodes(aParentNode)
|
80
80
|
subnodes = aParentNode.subnodes
|
81
81
|
broadcast(:before_subnodes, aParentNode, subnodes)
|
@@ -88,7 +88,7 @@ module Rley
|
|
88
88
|
|
89
89
|
# Visit event. The visitor is about to visit one given subnode of a non
|
90
90
|
# terminal node.
|
91
|
-
# @param aParentNode [
|
91
|
+
# @param aParentNode [CompositeNode] the parent node.
|
92
92
|
# @param index [integer] index of child subnode
|
93
93
|
def traverse_given_subnode(aParentNode, index)
|
94
94
|
subnode = aParentNode.subnodes[index]
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
|
-
|
5
3
|
require_relative 'parser'
|
6
4
|
require_relative 'ast_visitor'
|
7
5
|
require_relative '../syntax/match_closest'
|
@@ -9,7 +7,7 @@ require_relative '../syntax/match_closest'
|
|
9
7
|
module Rley # This module is used as a namespace
|
10
8
|
# Namespace for classes that define RGN (Rley Grammar Notation)
|
11
9
|
module RGN # This module is used as a namespace
|
12
|
-
# Structure used by Rley to generate
|
10
|
+
# Structure used by Rley to generate implicit production rules.
|
13
11
|
RawRule = Struct.new(:lhs, :rhs, :tag, :simple, :constraints)
|
14
12
|
|
15
13
|
# Builder GoF pattern. Builder builds a complex object
|
@@ -67,10 +65,10 @@ module Rley # This module is used as a namespace
|
|
67
65
|
# Add the given marker symbol to the grammar of the language
|
68
66
|
# @param aMarkerSymbol [String] A marker symbol
|
69
67
|
# @return [void]
|
70
|
-
def add_marker(aMarkerSymbol)
|
71
|
-
|
72
|
-
|
73
|
-
end
|
68
|
+
# def add_marker(aMarkerSymbol)
|
69
|
+
# new_symb = build_symbol(Syntax::Marker, aMarkerSymbol)
|
70
|
+
# symbols[new_symb.name] = new_symb
|
71
|
+
# end
|
74
72
|
|
75
73
|
# Add a production rule in the grammar given one
|
76
74
|
# key-value pair of the form: String => String.
|
@@ -87,7 +85,7 @@ module Rley # This module is used as a namespace
|
|
87
85
|
def add_production(aProductionRepr)
|
88
86
|
aProductionRepr.each_pair do |(lhs_name, rhs_repr)|
|
89
87
|
lhs = get_grm_symbol(lhs_name)
|
90
|
-
rhs = rhs_repr.
|
88
|
+
rhs = rhs_repr.is_a?(Array) && rhs_repr.empty? ? '' : rhs_repr.strip
|
91
89
|
constraints = []
|
92
90
|
if rhs.empty?
|
93
91
|
rhs_members = []
|
@@ -98,7 +96,7 @@ module Rley # This module is used as a namespace
|
|
98
96
|
visitor.subscribe(self)
|
99
97
|
visitor.start
|
100
98
|
root_node = ast.root
|
101
|
-
constraints = root_node.constraints unless root_node.
|
99
|
+
constraints = root_node.constraints unless root_node.is_a?(SymbolNode)
|
102
100
|
|
103
101
|
rhs_members = visitor2rhs.delete(visitor)
|
104
102
|
end
|
@@ -122,12 +120,12 @@ module Rley # This module is used as a namespace
|
|
122
120
|
|
123
121
|
# Check that each terminal appears at least in a rhs of a production
|
124
122
|
all_terminals = symbols.values.select do |a_symb|
|
125
|
-
a_symb.
|
123
|
+
a_symb.is_a?(Syntax::Terminal)
|
126
124
|
end
|
127
125
|
in_use = Set.new
|
128
126
|
productions.each do |prod|
|
129
127
|
prod.rhs.members.each do |symb|
|
130
|
-
in_use << symb if symb.
|
128
|
+
in_use << symb if symb.is_a?(Syntax::Terminal)
|
131
129
|
end
|
132
130
|
end
|
133
131
|
|
@@ -295,7 +293,7 @@ module Rley # This module is used as a namespace
|
|
295
293
|
aProductionRepr.each_pair do |(lhs_name, rhs_repr)|
|
296
294
|
lhs = get_grm_symbol(lhs_name)
|
297
295
|
|
298
|
-
if rhs_repr.
|
296
|
+
if rhs_repr.is_a?(String)
|
299
297
|
rhs = rhs_repr.strip.scan(/\S+/)
|
300
298
|
else
|
301
299
|
rhs = rhs_repr
|
@@ -340,7 +338,7 @@ module Rley # This module is used as a namespace
|
|
340
338
|
# @param aSymbolArg [GrmSymbol-like or String]
|
341
339
|
# @return [Array] list of grammar symbols
|
342
340
|
def build_symbol(aClass, aSymbolArg)
|
343
|
-
if aSymbolArg.
|
341
|
+
if aSymbolArg.is_a?(Syntax::GrmSymbol)
|
344
342
|
aSymbolArg
|
345
343
|
else
|
346
344
|
aClass.new(aSymbolArg)
|
@@ -387,7 +385,7 @@ module Rley # This module is used as a namespace
|
|
387
385
|
end
|
388
386
|
|
389
387
|
def node_base_name(aNode)
|
390
|
-
if aNode.
|
388
|
+
if aNode.is_a?(SymbolNode)
|
391
389
|
aNode.name
|
392
390
|
else
|
393
391
|
sequence_name(aNode)
|
data/lib/rley/rgn/parser.rb
CHANGED
@@ -37,7 +37,7 @@ module Rley
|
|
37
37
|
|
38
38
|
# Parse the given RGN snippet into a parse tree.
|
39
39
|
# @param source [String] Snippet to parse
|
40
|
-
# @return [Rley::ParseTree] A parse tree equivalent to the RGN input.
|
40
|
+
# @return [Rley::PTree::ParseTree] A parse tree equivalent to the RGN input.
|
41
41
|
def parse(source)
|
42
42
|
lexer = Tokenizer.new(source)
|
43
43
|
result = engine.parse(lexer.tokens)
|
@@ -49,7 +49,7 @@ module Rley
|
|
49
49
|
raise SyntaxError, line1 + line2
|
50
50
|
end
|
51
51
|
|
52
|
-
|
52
|
+
engine.convert(result) # engine.to_ptree(result)
|
53
53
|
end
|
54
54
|
end # class
|
55
55
|
end # module
|
data/lib/rley/rgn/tokenizer.rb
CHANGED
data/lib/rley/rley_error.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# File: rley_error.rb
|
4
|
-
|
5
3
|
module Rley # Module used as a namespace
|
6
4
|
# @abstract
|
7
5
|
# Base class for any exception explicitly raised by Rley code.
|
8
6
|
class RleyError < StandardError
|
9
7
|
end # class
|
10
8
|
end # module
|
11
|
-
|
12
|
-
# End of file
|
@@ -34,6 +34,12 @@ module Rley # This module is used as a namespace
|
|
34
34
|
def key
|
35
35
|
@key ||= to_string(0)
|
36
36
|
end
|
37
|
+
|
38
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
39
|
+
# @param aVisitor[ParseTreeVisitor] the visitor
|
40
|
+
def accept(aVisitor)
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
37
43
|
end # class
|
38
44
|
end # module
|
39
45
|
end # module
|
@@ -51,13 +51,13 @@ module Rley # This module is used as a namespace
|
|
51
51
|
# parse trees. That enumerator will generate a parse tree when
|
52
52
|
# called with `next` method.
|
53
53
|
# @return [Enumerator]
|
54
|
-
def to_ptree_enum
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
54
|
+
# def to_ptree_enum
|
55
|
+
# # How to implement?
|
56
|
+
# # One visits the forest => beware of dependency
|
57
|
+
# # At each visited item create a corresponding tree node.
|
58
|
+
# # At end of visit & stack not empty
|
59
|
+
# # Re-generate another ptree
|
60
|
+
# end
|
61
61
|
|
62
62
|
# Part of the 'visitee' role in the Visitor design pattern.
|
63
63
|
# A visitee is expected to accept the visit from a visitor object
|
data/lib/rley/sppf/sppf_node.rb
CHANGED
@@ -20,9 +20,23 @@ module Rley # This module is used as a namespace
|
|
20
20
|
# Return the origin, that is, the index of the
|
21
21
|
# first token matched by this node.
|
22
22
|
# @return [Integer]
|
23
|
-
def origin
|
23
|
+
def origin # steep:ignore MethodBodyTypeMismatch
|
24
24
|
range.low
|
25
25
|
end
|
26
|
+
|
27
|
+
# Emit a (formatted) string representation of the node.
|
28
|
+
# Mainly used for diagnosis/debugging purposes.
|
29
|
+
# @param indentation [Integer]
|
30
|
+
# @return [String]
|
31
|
+
def to_string(indentation)
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
36
|
+
# @param aVisitor[ParseForestVisitor] the visitor
|
37
|
+
def accept(aVisitor)
|
38
|
+
raise NotImplementedError
|
39
|
+
end
|
26
40
|
end # class
|
27
41
|
end # module
|
28
42
|
end # module
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
3
|
require_relative 'terminal'
|
5
4
|
require_relative 'non_terminal'
|
6
5
|
require_relative 'production'
|
@@ -54,14 +53,6 @@ module Rley # This module is used as a namespace
|
|
54
53
|
symbols.merge!(new_symbs)
|
55
54
|
end
|
56
55
|
|
57
|
-
# Add the given marker symbol to the grammar of the language
|
58
|
-
# @param aMarkerSymbol [Syntax::Marker] A mazker symbol
|
59
|
-
# @return [void]
|
60
|
-
def add_marker(aMarkerSymbol)
|
61
|
-
new_symb = build_symbol(Marker, aMarkerSymbol)
|
62
|
-
symbols[aMarkerSymbol.name] = new_symb
|
63
|
-
end
|
64
|
-
|
65
56
|
# Add a production rule in the grammar given one
|
66
57
|
# key-value pair of the form: String => Array.
|
67
58
|
# Where the key is the name of the non-terminal appearing in the
|
@@ -107,12 +98,12 @@ module Rley # This module is used as a namespace
|
|
107
98
|
|
108
99
|
# Check that each terminal appears at least in a rhs of a production
|
109
100
|
all_terminals = symbols.values.select do |a_symb|
|
110
|
-
a_symb.
|
101
|
+
a_symb.is_a?(Terminal)
|
111
102
|
end
|
112
103
|
in_use = Set.new
|
113
104
|
productions.each do |prod|
|
114
105
|
prod.rhs.members.each do |symb|
|
115
|
-
in_use << symb if symb.
|
106
|
+
in_use << symb if symb.is_a?(Syntax::Terminal)
|
116
107
|
end
|
117
108
|
end
|
118
109
|
|
@@ -169,7 +160,7 @@ module Rley # This module is used as a namespace
|
|
169
160
|
# @param aSymbolArg [GrmSymbol-like or String]
|
170
161
|
# @return [Array] list of grammar symbols
|
171
162
|
def build_symbol(aClass, aSymbolArg)
|
172
|
-
if aSymbolArg.
|
163
|
+
if aSymbolArg.is_a?(GrmSymbol)
|
173
164
|
aSymbolArg
|
174
165
|
else
|
175
166
|
aClass.new(aSymbolArg)
|