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.
- checksums.yaml +4 -4
- data/.rubocop.yml +362 -62
- data/.travis.yml +6 -6
- data/CHANGELOG.md +20 -4
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/examples/NLP/engtagger.rb +193 -190
- data/examples/NLP/nano_eng/nano_en_demo.rb +7 -11
- data/examples/NLP/nano_eng/nano_grammar.rb +21 -21
- data/examples/NLP/pico_en_demo.rb +2 -2
- data/examples/data_formats/JSON/cli_options.rb +1 -1
- data/examples/data_formats/JSON/json_ast_builder.rb +21 -27
- data/examples/data_formats/JSON/json_ast_nodes.rb +12 -21
- data/examples/data_formats/JSON/json_demo.rb +1 -2
- data/examples/data_formats/JSON/json_grammar.rb +13 -13
- data/examples/data_formats/JSON/json_lexer.rb +8 -8
- data/examples/data_formats/JSON/json_minifier.rb +1 -1
- data/examples/general/calc_iter1/calc_ast_builder.rb +13 -10
- data/examples/general/calc_iter1/calc_ast_nodes.rb +23 -37
- data/examples/general/calc_iter1/calc_grammar.rb +7 -6
- data/examples/general/calc_iter1/calc_lexer.rb +6 -4
- data/examples/general/calc_iter1/spec/calculator_spec.rb +5 -5
- data/examples/general/calc_iter2/calc_ast_builder.rb +5 -3
- data/examples/general/calc_iter2/calc_ast_nodes.rb +27 -43
- data/examples/general/calc_iter2/calc_grammar.rb +12 -12
- data/examples/general/calc_iter2/calc_lexer.rb +11 -10
- data/examples/general/calc_iter2/spec/calculator_spec.rb +26 -26
- data/examples/general/left.rb +2 -2
- data/examples/general/right.rb +2 -2
- data/lib/rley.rb +1 -1
- data/lib/rley/base/dotted_item.rb +28 -31
- data/lib/rley/base/grm_items_builder.rb +6 -0
- data/lib/rley/constants.rb +2 -2
- data/lib/rley/engine.rb +22 -25
- data/lib/rley/formatter/asciitree.rb +3 -3
- data/lib/rley/formatter/bracket_notation.rb +1 -8
- data/lib/rley/formatter/debug.rb +6 -6
- data/lib/rley/formatter/json.rb +2 -2
- data/lib/rley/gfg/call_edge.rb +1 -1
- data/lib/rley/gfg/edge.rb +5 -5
- data/lib/rley/gfg/end_vertex.rb +2 -6
- data/lib/rley/gfg/epsilon_edge.rb +1 -5
- data/lib/rley/gfg/grm_flow_graph.rb +27 -23
- data/lib/rley/gfg/item_vertex.rb +10 -10
- data/lib/rley/gfg/non_terminal_vertex.rb +4 -4
- data/lib/rley/gfg/scan_edge.rb +1 -1
- data/lib/rley/gfg/shortcut_edge.rb +2 -2
- data/lib/rley/gfg/start_vertex.rb +4 -8
- data/lib/rley/gfg/vertex.rb +43 -39
- data/lib/rley/interface.rb +16 -0
- data/lib/rley/lexical/token_range.rb +6 -6
- data/lib/rley/notation/all_notation_nodes.rb +2 -0
- data/lib/rley/notation/ast_builder.rb +191 -0
- data/lib/rley/notation/ast_node.rb +44 -0
- data/lib/rley/notation/ast_visitor.rb +113 -0
- data/lib/rley/notation/grammar.rb +49 -0
- data/lib/rley/notation/grammar_builder.rb +504 -0
- data/lib/rley/notation/grouping_node.rb +23 -0
- data/lib/rley/notation/parser.rb +56 -0
- data/lib/rley/notation/sequence_node.rb +35 -0
- data/lib/rley/notation/symbol_node.rb +29 -0
- data/lib/rley/notation/tokenizer.rb +192 -0
- data/lib/rley/parse_forest_visitor.rb +5 -5
- data/lib/rley/parse_rep/ast_base_builder.rb +48 -11
- data/lib/rley/parse_rep/cst_builder.rb +5 -6
- data/lib/rley/parse_rep/parse_forest_builder.rb +22 -18
- data/lib/rley/parse_rep/parse_forest_factory.rb +3 -3
- data/lib/rley/parse_rep/parse_rep_creator.rb +14 -16
- data/lib/rley/parse_rep/parse_tree_builder.rb +4 -4
- data/lib/rley/parse_rep/parse_tree_factory.rb +27 -27
- data/lib/rley/parse_tree_visitor.rb +1 -1
- data/lib/rley/parser/error_reason.rb +4 -5
- data/lib/rley/parser/gfg_chart.rb +118 -26
- data/lib/rley/parser/gfg_parsing.rb +22 -33
- data/lib/rley/parser/parse_entry.rb +25 -31
- data/lib/rley/parser/parse_entry_set.rb +19 -16
- data/lib/rley/parser/parse_entry_tracker.rb +4 -4
- data/lib/rley/parser/parse_tracer.rb +13 -13
- data/lib/rley/parser/parse_walker_factory.rb +23 -28
- data/lib/rley/ptree/non_terminal_node.rb +7 -5
- data/lib/rley/ptree/parse_tree.rb +3 -3
- data/lib/rley/ptree/parse_tree_node.rb +5 -5
- data/lib/rley/ptree/terminal_node.rb +7 -7
- data/lib/rley/rley_error.rb +12 -12
- data/lib/rley/sppf/alternative_node.rb +6 -6
- data/lib/rley/sppf/composite_node.rb +7 -7
- data/lib/rley/sppf/epsilon_node.rb +3 -3
- data/lib/rley/sppf/leaf_node.rb +3 -3
- data/lib/rley/sppf/parse_forest.rb +16 -16
- data/lib/rley/sppf/sppf_node.rb +7 -8
- data/lib/rley/sppf/token_node.rb +3 -3
- data/lib/rley/syntax/{grammar_builder.rb → base_grammar_builder.rb} +61 -23
- data/lib/rley/syntax/grammar.rb +5 -5
- data/lib/rley/syntax/grm_symbol.rb +7 -7
- data/lib/rley/syntax/match_closest.rb +43 -0
- data/lib/rley/syntax/non_terminal.rb +9 -15
- data/lib/rley/syntax/production.rb +16 -10
- data/lib/rley/syntax/symbol_seq.rb +7 -9
- data/lib/rley/syntax/terminal.rb +4 -5
- data/lib/rley/syntax/verbatim_symbol.rb +3 -3
- data/lib/support/base_tokenizer.rb +19 -18
- data/spec/rley/base/dotted_item_spec.rb +2 -2
- data/spec/rley/engine_spec.rb +23 -21
- data/spec/rley/formatter/asciitree_spec.rb +7 -7
- data/spec/rley/formatter/bracket_notation_spec.rb +13 -13
- data/spec/rley/formatter/json_spec.rb +1 -1
- data/spec/rley/gfg/end_vertex_spec.rb +5 -5
- data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -2
- data/spec/rley/gfg/item_vertex_spec.rb +10 -10
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +3 -3
- data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
- data/spec/rley/gfg/start_vertex_spec.rb +5 -5
- data/spec/rley/gfg/vertex_spec.rb +3 -3
- data/spec/rley/lexical/token_range_spec.rb +16 -16
- data/spec/rley/lexical/token_spec.rb +2 -2
- data/spec/rley/notation/grammar_builder_spec.rb +302 -0
- data/spec/rley/notation/parser_spec.rb +184 -0
- data/spec/rley/notation/tokenizer_spec.rb +370 -0
- data/spec/rley/parse_forest_visitor_spec.rb +165 -163
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +44 -44
- data/spec/rley/parse_rep/ast_builder_spec.rb +6 -7
- data/spec/rley/parse_rep/cst_builder_spec.rb +5 -5
- data/spec/rley/parse_rep/groucho_spec.rb +24 -26
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +27 -27
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -8
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +3 -3
- data/spec/rley/parse_tree_visitor_spec.rb +10 -8
- data/spec/rley/parser/dangling_else_spec.rb +445 -0
- data/spec/rley/parser/error_reason_spec.rb +6 -6
- data/spec/rley/parser/gfg_earley_parser_spec.rb +120 -12
- data/spec/rley/parser/gfg_parsing_spec.rb +6 -13
- data/spec/rley/parser/parse_entry_spec.rb +19 -19
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -10
- data/spec/rley/ptree/non_terminal_node_spec.rb +5 -3
- data/spec/rley/ptree/parse_tree_node_spec.rb +4 -4
- data/spec/rley/ptree/terminal_node_spec.rb +6 -6
- data/spec/rley/sppf/alternative_node_spec.rb +6 -6
- data/spec/rley/sppf/non_terminal_node_spec.rb +3 -3
- data/spec/rley/sppf/token_node_spec.rb +4 -4
- data/spec/rley/support/ambiguous_grammar_helper.rb +4 -5
- data/spec/rley/support/grammar_abc_helper.rb +3 -5
- data/spec/rley/support/grammar_ambig01_helper.rb +5 -6
- data/spec/rley/support/grammar_arr_int_helper.rb +5 -6
- data/spec/rley/support/grammar_b_expr_helper.rb +5 -6
- data/spec/rley/support/grammar_int_seq_helper.rb +51 -0
- data/spec/rley/support/grammar_l0_helper.rb +14 -17
- data/spec/rley/support/grammar_pb_helper.rb +8 -7
- data/spec/rley/support/grammar_sppf_helper.rb +3 -3
- data/spec/rley/syntax/{grammar_builder_spec.rb → base_grammar_builder_spec.rb} +35 -16
- data/spec/rley/syntax/grammar_spec.rb +6 -6
- data/spec/rley/syntax/grm_symbol_spec.rb +1 -1
- data/spec/rley/syntax/match_closest_spec.rb +46 -0
- data/spec/rley/syntax/non_terminal_spec.rb +8 -8
- data/spec/rley/syntax/production_spec.rb +17 -13
- data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
- data/spec/rley/syntax/terminal_spec.rb +5 -5
- data/spec/rley/syntax/verbatim_symbol_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -12
- data/spec/support/base_tokenizer_spec.rb +7 -2
- metadata +48 -74
- data/.simplecov +0 -7
- data/lib/rley/parser/parse_state.rb +0 -83
- data/lib/rley/parser/parse_state_tracker.rb +0 -59
- data/lib/rley/parser/state_set.rb +0 -101
- data/spec/rley/parser/parse_state_spec.rb +0 -125
- data/spec/rley/parser/parse_tracer_spec.rb +0 -200
- data/spec/rley/parser/state_set_spec.rb +0 -130
data/lib/rley/sppf/sppf_node.rb
CHANGED
@@ -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
|
-
|
26
|
-
end
|
23
|
+
def origin
|
24
|
+
range.low
|
25
|
+
end
|
27
26
|
end # class
|
28
27
|
end # module
|
29
28
|
end # module
|
data/lib/rley/sppf/token_node.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
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 =
|
83
|
+
lhs = get_grm_symbol(lhs_name)
|
76
84
|
case rhs_repr
|
77
85
|
when Array
|
78
|
-
rhs_members = rhs_repr.map { |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|
|
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,
|
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
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
166
|
-
unless
|
167
|
-
|
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
|
-
|
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
|
data/lib/rley/syntax/grammar.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
33
|
+
false
|
34
34
|
end
|
35
35
|
|
36
36
|
# @return [Boolean] true iff the symbol is generative.
|
37
|
-
def generative?
|
38
|
-
|
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
|
-
|
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
|
-
|
62
|
+
@generative
|
59
63
|
end
|
60
64
|
|
61
65
|
# @return [Boolen] true iff the production is nullable
|
62
|
-
def nullable?
|
63
|
-
|
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
|
-
|
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
|