rley 0.3.04 → 0.3.05
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -3
- data/CHANGELOG.md +3 -0
- data/Rakefile +30 -30
- data/examples/parsers/parsing_L0.rb +1 -1
- data/examples/parsers/parsing_L1.rb +1 -1
- data/examples/parsers/parsing_abc.rb +1 -1
- data/examples/parsers/parsing_ambig.rb +1 -1
- data/examples/parsers/parsing_another.rb +1 -1
- data/examples/parsers/parsing_b_expr.rb +1 -1
- data/examples/parsers/parsing_err_expr.rb +1 -1
- data/examples/parsers/parsing_groucho.rb +1 -1
- data/examples/parsers/parsing_right_recursive.rb +1 -1
- data/examples/parsers/parsing_tricky.rb +1 -1
- data/lib/rley/constants.rb +2 -2
- data/lib/rley/formatter/base_formatter.rb +0 -2
- data/lib/rley/formatter/debug.rb +0 -2
- data/lib/rley/formatter/json.rb +1 -3
- data/lib/rley/gfg/call_edge.rb +31 -30
- data/lib/rley/gfg/edge.rb +22 -23
- data/lib/rley/gfg/end_vertex.rb +22 -24
- data/lib/rley/gfg/epsilon_edge.rb +20 -21
- data/lib/rley/gfg/grm_flow_graph.rb +39 -39
- data/lib/rley/gfg/item_vertex.rb +16 -17
- data/lib/rley/gfg/non_terminal_vertex.rb +3 -4
- data/lib/rley/gfg/return_edge.rb +32 -31
- data/lib/rley/gfg/scan_edge.rb +25 -26
- data/lib/rley/gfg/shortcut_edge.rb +25 -26
- data/lib/rley/gfg/start_vertex.rb +0 -2
- data/lib/rley/gfg/vertex.rb +8 -8
- data/lib/rley/parse_forest_visitor.rb +113 -115
- data/lib/rley/parse_tree_visitor.rb +0 -2
- data/lib/rley/parser/base_parser.rb +27 -27
- data/lib/rley/parser/chart.rb +14 -14
- data/lib/rley/parser/dotted_item.rb +33 -33
- data/lib/rley/parser/earley_parser.rb +6 -6
- data/lib/rley/parser/gfg_chart.rb +8 -15
- data/lib/rley/parser/gfg_earley_parser.rb +15 -13
- data/lib/rley/parser/gfg_parsing.rb +26 -22
- data/lib/rley/parser/grm_items_builder.rb +3 -2
- data/lib/rley/parser/parse_entry.rb +3 -9
- data/lib/rley/parser/parse_entry_set.rb +14 -19
- data/lib/rley/parser/parse_entry_tracker.rb +56 -56
- data/lib/rley/parser/parse_forest_builder.rb +215 -214
- data/lib/rley/parser/parse_forest_factory.rb +57 -56
- data/lib/rley/parser/parse_state.rb +8 -11
- data/lib/rley/parser/parse_state_tracker.rb +56 -56
- data/lib/rley/parser/parse_tracer.rb +3 -3
- data/lib/rley/parser/parse_tree_builder.rb +10 -10
- data/lib/rley/parser/parse_walker_factory.rb +30 -33
- data/lib/rley/parser/parsing.rb +8 -8
- data/lib/rley/parser/state_set.rb +23 -26
- data/lib/rley/ptree/non_terminal_node.rb +1 -1
- data/lib/rley/ptree/token_range.rb +2 -2
- data/lib/rley/sppf/alternative_node.rb +32 -34
- data/lib/rley/sppf/composite_node.rb +27 -27
- data/lib/rley/sppf/epsilon_node.rb +26 -27
- data/lib/rley/sppf/leaf_node.rb +11 -12
- data/lib/rley/sppf/non_terminal_node.rb +37 -38
- data/lib/rley/sppf/sppf_node.rb +1 -1
- data/lib/rley/sppf/token_node.rb +29 -29
- data/lib/rley/syntax/grammar.rb +1 -3
- data/lib/rley/syntax/grammar_builder.rb +8 -8
- data/lib/rley/syntax/non_terminal.rb +2 -4
- data/lib/rley/syntax/production.rb +3 -3
- data/lib/rley/syntax/symbol_seq.rb +1 -1
- data/spec/rley/gfg/call_edge_spec.rb +50 -51
- data/spec/rley/gfg/edge_spec.rb +33 -33
- data/spec/rley/gfg/end_vertex_spec.rb +26 -27
- data/spec/rley/gfg/epsilon_edge_spec.rb +25 -25
- data/spec/rley/gfg/grm_flow_graph_spec.rb +1 -1
- data/spec/rley/gfg/item_vertex_spec.rb +3 -4
- data/spec/rley/gfg/return_edge_spec.rb +51 -51
- data/spec/rley/gfg/scan_edge_spec.rb +32 -30
- data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
- data/spec/rley/gfg/vertex_spec.rb +3 -3
- data/spec/rley/parse_forest_visitor_spec.rb +239 -238
- data/spec/rley/parser/dotted_item_spec.rb +1 -1
- data/spec/rley/parser/earley_parser_spec.rb +16 -16
- data/spec/rley/parser/gfg_earley_parser_spec.rb +30 -31
- data/spec/rley/parser/gfg_parsing_spec.rb +11 -10
- data/spec/rley/parser/grm_items_builder_spec.rb +2 -2
- data/spec/rley/parser/parse_entry_set_spec.rb +4 -4
- data/spec/rley/parser/parse_entry_spec.rb +0 -2
- data/spec/rley/parser/parse_forest_builder_spec.rb +82 -57
- data/spec/rley/parser/parse_forest_factory_spec.rb +84 -82
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -9
- data/spec/rley/parser/parsing_spec.rb +0 -1
- data/spec/rley/sppf/alternative_node_spec.rb +2 -2
- data/spec/rley/sppf/non_terminal_node_spec.rb +0 -1
- data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
- data/spec/rley/support/expectation_helper.rb +37 -36
- data/spec/rley/support/grammar_abc_helper.rb +17 -17
- data/spec/rley/support/grammar_b_expr_helper.rb +40 -39
- data/spec/rley/support/grammar_helper.rb +2 -1
- data/spec/rley/support/{grammar_L0_helper.rb → grammar_l0_helper.rb} +82 -81
- data/spec/rley/support/grammar_sppf_helper.rb +24 -25
- data/spec/rley/syntax/grammar_spec.rb +1 -1
- metadata +2 -2
@@ -6,8 +6,8 @@ module Rley # This module is used as a namespace
|
|
6
6
|
# let's assume that the integer literal '3' is the fifth input token and
|
7
7
|
# that the '+' and '11' tokens are respectively at position 6 and 7;
|
8
8
|
# then the token range associated with E is [5, 7]
|
9
|
-
# While the parse tree/forest is being constructed the boundaries of the
|
10
|
-
# can be temporarily undefined (= set to nil)
|
9
|
+
# While the parse tree/forest is being constructed the boundaries of the
|
10
|
+
# token range can be temporarily undefined (= set to nil)
|
11
11
|
class TokenRange
|
12
12
|
# The index of the lower bound of token range
|
13
13
|
attr_reader(:low)
|
@@ -1,34 +1,32 @@
|
|
1
|
-
require_relative 'composite_node'
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module SPPF # This module is used as a namespace
|
5
|
-
# A node in a parse forest that is a child
|
6
|
-
# of a parent node with :or refinement
|
7
|
-
class AlternativeNode < CompositeNode
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end # module
|
34
|
-
# End of file
|
1
|
+
require_relative 'composite_node'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module SPPF # This module is used as a namespace
|
5
|
+
# A node in a parse forest that is a child
|
6
|
+
# of a parent node with :or refinement
|
7
|
+
class AlternativeNode < CompositeNode
|
8
|
+
# GFG vertex label
|
9
|
+
attr_reader(:label)
|
10
|
+
|
11
|
+
# Link to lhs symbol
|
12
|
+
attr_reader(:symbol)
|
13
|
+
|
14
|
+
# @param aVertex [ItemVertex] An GFG vertex that corresponds
|
15
|
+
# a dotted item (with the dot at the end)for the alternative under
|
16
|
+
# consideration.
|
17
|
+
# @param aRange [TokenRange]
|
18
|
+
def initialize(aVertex, aRange)
|
19
|
+
super(aRange)
|
20
|
+
@label = aVertex.label
|
21
|
+
@symbol = aVertex.dotted_item.lhs
|
22
|
+
end
|
23
|
+
|
24
|
+
# Emit a (formatted) string representation of the node.
|
25
|
+
# Mainly used for diagnosis/debugging purposes.
|
26
|
+
def to_string(indentation)
|
27
|
+
return "Alt(#{label})#{range.to_string(indentation)}"
|
28
|
+
end
|
29
|
+
end # class
|
30
|
+
end # module
|
31
|
+
end # module
|
32
|
+
# End of file
|
@@ -1,27 +1,27 @@
|
|
1
|
-
require_relative 'sppf_node'
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module SPPF # This module is used as a namespace
|
5
|
-
# Abstract class. The generalization for nodes that have
|
6
|
-
# children node(s).
|
7
|
-
class CompositeNode < SPPFNode
|
8
|
-
# Array of sub-nodes.
|
9
|
-
attr_reader(:subnodes)
|
10
|
-
|
11
|
-
def initialize(aRange)
|
12
|
-
super(aRange)
|
13
|
-
@subnodes = []
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
def add_subnode(aSubnode)
|
18
|
-
subnodes.unshift(aSubnode)
|
19
|
-
end
|
20
|
-
|
21
|
-
def key()
|
22
|
-
@key ||= to_string(0)
|
23
|
-
end
|
24
|
-
end # class
|
25
|
-
end # module
|
26
|
-
end # module
|
27
|
-
# End of file
|
1
|
+
require_relative 'sppf_node'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module SPPF # This module is used as a namespace
|
5
|
+
# Abstract class. The generalization for nodes that have
|
6
|
+
# children node(s).
|
7
|
+
class CompositeNode < SPPFNode
|
8
|
+
# Array of sub-nodes.
|
9
|
+
attr_reader(:subnodes)
|
10
|
+
|
11
|
+
def initialize(aRange)
|
12
|
+
super(aRange)
|
13
|
+
@subnodes = []
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def add_subnode(aSubnode)
|
18
|
+
subnodes.unshift(aSubnode)
|
19
|
+
end
|
20
|
+
|
21
|
+
def key()
|
22
|
+
@key ||= to_string(0)
|
23
|
+
end
|
24
|
+
end # class
|
25
|
+
end # module
|
26
|
+
end # module
|
27
|
+
# End of file
|
@@ -1,27 +1,26 @@
|
|
1
|
-
require_relative 'leaf_node'
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module SPPF # This module is used as a namespace
|
5
|
-
# A leaf node in a parse forest that matches an empty
|
6
|
-
# string from the input
|
7
|
-
class EpsilonNode < LeafNode
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
range
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# End of file
|
1
|
+
require_relative 'leaf_node'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module SPPF # This module is used as a namespace
|
5
|
+
# A leaf node in a parse forest that matches an empty
|
6
|
+
# string from the input
|
7
|
+
class EpsilonNode < LeafNode
|
8
|
+
# aPosition is the position of the token in the input stream.
|
9
|
+
def initialize(aPosition)
|
10
|
+
range = { low: aPosition, high: aPosition }
|
11
|
+
super(range)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Emit a (formatted) string representation of the node.
|
15
|
+
# Mainly used for diagnosis/debugging purposes.
|
16
|
+
def to_string(indentation)
|
17
|
+
return "_#{range.to_string(indentation)}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def key()
|
21
|
+
@key ||= to_string(0)
|
22
|
+
end
|
23
|
+
end # class
|
24
|
+
end # module
|
25
|
+
end # module
|
26
|
+
# End of file
|
data/lib/rley/sppf/leaf_node.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
require_relative 'sppf_node'
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module SPPF # This module is used as a namespace
|
5
|
-
# Abstract class. The generalization for nodes that don't have
|
6
|
-
# child node.
|
7
|
-
class LeafNode < SPPFNode
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# End of file
|
1
|
+
require_relative 'sppf_node'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module SPPF # This module is used as a namespace
|
5
|
+
# Abstract class. The generalization for nodes that don't have
|
6
|
+
# child node.
|
7
|
+
class LeafNode < SPPFNode
|
8
|
+
end # class
|
9
|
+
end # module
|
10
|
+
end # module
|
11
|
+
# End of file
|
@@ -1,38 +1,37 @@
|
|
1
|
-
require_relative 'composite_node'
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module SPPF # This module is used as a namespace
|
5
|
-
# A node in a parse forest that matches exactly one
|
6
|
-
# non-terminal symbol
|
7
|
-
class NonTerminalNode < CompositeNode
|
8
|
-
# Link to the non-terminal symbol
|
9
|
-
attr_reader(:symbol)
|
10
|
-
|
11
|
-
# Indication on how the sub-nodes contribute to the 'success'
|
12
|
-
# of parent node. Possible values: :and, :or
|
13
|
-
attr_accessor :refinement
|
14
|
-
|
15
|
-
def initialize(aNonTerminal, aRange)
|
16
|
-
super(aRange)
|
17
|
-
@symbol = aNonTerminal
|
18
|
-
@refinement = :and
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_subnode(aSubnode)
|
22
|
-
if refinement == :or
|
23
|
-
subnodes << aSubnode
|
24
|
-
else
|
25
|
-
super(aSubnode)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Emit a (formatted) string representation of the node.
|
30
|
-
# Mainly used for diagnosis/debugging purposes.
|
31
|
-
def to_string(indentation)
|
32
|
-
return "#{symbol.name}#{range.to_string(indentation)}"
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# End of file
|
1
|
+
require_relative 'composite_node'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module SPPF # This module is used as a namespace
|
5
|
+
# A node in a parse forest that matches exactly one
|
6
|
+
# non-terminal symbol
|
7
|
+
class NonTerminalNode < CompositeNode
|
8
|
+
# Link to the non-terminal symbol
|
9
|
+
attr_reader(:symbol)
|
10
|
+
|
11
|
+
# Indication on how the sub-nodes contribute to the 'success'
|
12
|
+
# of parent node. Possible values: :and, :or
|
13
|
+
attr_accessor :refinement
|
14
|
+
|
15
|
+
def initialize(aNonTerminal, aRange)
|
16
|
+
super(aRange)
|
17
|
+
@symbol = aNonTerminal
|
18
|
+
@refinement = :and
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_subnode(aSubnode)
|
22
|
+
if refinement == :or
|
23
|
+
subnodes << aSubnode
|
24
|
+
else
|
25
|
+
super(aSubnode)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Emit a (formatted) string representation of the node.
|
30
|
+
# Mainly used for diagnosis/debugging purposes.
|
31
|
+
def to_string(indentation)
|
32
|
+
return "#{symbol.name}#{range.to_string(indentation)}"
|
33
|
+
end
|
34
|
+
end # class
|
35
|
+
end # module
|
36
|
+
end # module
|
37
|
+
# End of file
|
data/lib/rley/sppf/sppf_node.rb
CHANGED
data/lib/rley/sppf/token_node.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
require_relative 'leaf_node'
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module SPPF # This module is used as a namespace
|
5
|
-
# A node in a parse forest that matches exactly one
|
6
|
-
# token from the input
|
7
|
-
class TokenNode < LeafNode
|
8
|
-
attr_reader(:token)
|
9
|
-
|
10
|
-
# aPosition is the position of the token in the input stream.
|
11
|
-
def initialize(aToken, aPosition)
|
12
|
-
range = {low: aPosition, high: aPosition + 1}
|
13
|
-
super(range)
|
14
|
-
@token = aToken
|
15
|
-
end
|
16
|
-
|
17
|
-
# Emit a (formatted) string representation of the node.
|
18
|
-
# Mainly used for diagnosis/debugging purposes.
|
19
|
-
def to_string(indentation)
|
20
|
-
return "#{token.terminal.name}#{range.to_string(indentation)}"
|
21
|
-
end
|
22
|
-
|
23
|
-
def key()
|
24
|
-
@key ||= to_string(0)
|
25
|
-
end
|
26
|
-
end # class
|
27
|
-
end # module
|
28
|
-
end # module
|
29
|
-
# End of file
|
1
|
+
require_relative 'leaf_node'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module SPPF # This module is used as a namespace
|
5
|
+
# A node in a parse forest that matches exactly one
|
6
|
+
# token from the input
|
7
|
+
class TokenNode < LeafNode
|
8
|
+
attr_reader(:token)
|
9
|
+
|
10
|
+
# aPosition is the position of the token in the input stream.
|
11
|
+
def initialize(aToken, aPosition)
|
12
|
+
range = { low: aPosition, high: aPosition + 1 }
|
13
|
+
super(range)
|
14
|
+
@token = aToken
|
15
|
+
end
|
16
|
+
|
17
|
+
# Emit a (formatted) string representation of the node.
|
18
|
+
# Mainly used for diagnosis/debugging purposes.
|
19
|
+
def to_string(indentation)
|
20
|
+
return "#{token.terminal.name}#{range.to_string(indentation)}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def key()
|
24
|
+
@key ||= to_string(0)
|
25
|
+
end
|
26
|
+
end # class
|
27
|
+
end # module
|
28
|
+
end # module
|
29
|
+
# End of file
|
data/lib/rley/syntax/grammar.rb
CHANGED
@@ -53,7 +53,7 @@ module Rley # This module is used as a namespace
|
|
53
53
|
# Validation method. Return the validated list of productions
|
54
54
|
def validate_productions(theProductions)
|
55
55
|
msg = 'A grammar must have at least one production'
|
56
|
-
|
56
|
+
raise StandardError, msg if theProductions.nil? || theProductions.empty?
|
57
57
|
return theProductions
|
58
58
|
end
|
59
59
|
|
@@ -112,8 +112,6 @@ module Rley # This module is used as a namespace
|
|
112
112
|
return nullable
|
113
113
|
end
|
114
114
|
|
115
|
-
private
|
116
|
-
|
117
115
|
def add_symbol(aSymbol)
|
118
116
|
its_name = aSymbol.name
|
119
117
|
return if name2symbol.include? its_name
|
@@ -70,16 +70,16 @@ module Rley # This module is used as a namespace
|
|
70
70
|
# build the resulting grammar (if not yet done).
|
71
71
|
def grammar()
|
72
72
|
unless @grammar
|
73
|
-
|
73
|
+
raise StandardError, 'No symbol found for grammar' if symbols.empty?
|
74
74
|
if productions.empty?
|
75
|
-
|
75
|
+
raise StandardError, 'No production found for grammar'
|
76
76
|
end
|
77
77
|
|
78
78
|
# Check that each non-terminal appears at least once in lhs.
|
79
79
|
all_non_terminals = symbols.values.select { |s| s.is_a?(NonTerminal) }
|
80
80
|
all_non_terminals.each do |n_term|
|
81
81
|
next if productions.any? { |prod| n_term == prod.lhs }
|
82
|
-
|
82
|
+
raise StandardError, "Nonterminal #{n_term.name} not rewritten"
|
83
83
|
end
|
84
84
|
|
85
85
|
@grammar = Grammar.new(productions.dup)
|
@@ -114,11 +114,11 @@ module Rley # This module is used as a namespace
|
|
114
114
|
# @param aSymbolArg [GrmSymbol-like or String]
|
115
115
|
# @return [Array] list of grammar symbols
|
116
116
|
def build_symbol(aClass, aSymbolArg)
|
117
|
-
if aSymbolArg.kind_of?(GrmSymbol)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
a_symbol = if aSymbolArg.kind_of?(GrmSymbol)
|
118
|
+
aSymbolArg
|
119
|
+
else
|
120
|
+
aClass.new(aSymbolArg)
|
121
|
+
end
|
122
122
|
|
123
123
|
return a_symbol
|
124
124
|
end
|
@@ -6,15 +6,13 @@ module Rley # This module is used as a namespace
|
|
6
6
|
# a composition of terminal or non-terminal symbols
|
7
7
|
class NonTerminal < GrmSymbol
|
8
8
|
attr_writer(:nullable)
|
9
|
-
|
9
|
+
|
10
10
|
# Constructor.
|
11
11
|
# @param aName [String] The name of the grammar symbol.
|
12
12
|
def initialize(aName)
|
13
13
|
super(aName)
|
14
14
|
end
|
15
|
-
|
16
|
-
public
|
17
|
-
|
15
|
+
|
18
16
|
# @return [false/true] Return true if the symbol derives
|
19
17
|
# the empty string. As non-terminal symbol is nullable when it can
|
20
18
|
# can match to zero input token.
|
@@ -18,8 +18,8 @@ module Rley # This module is used as a namespace
|
|
18
18
|
|
19
19
|
# Provide common alternate names to lhs and rhs accessors
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
alias body rhs
|
22
|
+
alias head lhs
|
23
23
|
|
24
24
|
def initialize(aNonTerminal, theSymbols)
|
25
25
|
@lhs = valid_lhs(aNonTerminal)
|
@@ -40,7 +40,7 @@ module Rley # This module is used as a namespace
|
|
40
40
|
unless aNonTerminal.kind_of?(NonTerminal)
|
41
41
|
msg_prefix = 'Left side of production must be a non-terminal symbol'
|
42
42
|
msg_suffix = ", found a #{aNonTerminal.class} instead."
|
43
|
-
|
43
|
+
raise StandardError, msg_prefix + msg_suffix
|
44
44
|
end
|
45
45
|
|
46
46
|
return aNonTerminal
|