rley 0.7.06 → 0.8.01
Sign up to get free protection for your applications and to get access to all the features.
- 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
|