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/gfg/item_vertex.rb
CHANGED
@@ -40,33 +40,33 @@ module Rley # This module is used as a namespace
|
|
40
40
|
# The label of this vertex.
|
41
41
|
# It is the same as the label of the corresponding dotted item.
|
42
42
|
# @return [String] Label for this vertex
|
43
|
-
def label
|
44
|
-
|
43
|
+
def label
|
44
|
+
dotted_item.to_s
|
45
45
|
end
|
46
46
|
|
47
47
|
# Returns true if the dotted item has a dot at the end of the production.
|
48
48
|
# @return [Boolean]
|
49
|
-
def complete?
|
50
|
-
|
49
|
+
def complete?
|
50
|
+
dotted_item.reduce_item?
|
51
51
|
end
|
52
52
|
|
53
53
|
# Return the symbol before the dot.
|
54
54
|
# @return [Syntax::GrmSymbol, NilClass] Previous symbol otherwise nil.
|
55
|
-
def prev_symbol
|
56
|
-
|
55
|
+
def prev_symbol
|
56
|
+
dotted_item.prev_symbol
|
57
57
|
end
|
58
58
|
|
59
59
|
# Return the symbol after the dot.
|
60
60
|
# @return [Syntax::GrmSymbol, NilClass] Next grammar symbol otherwise nil.
|
61
|
-
def next_symbol
|
62
|
-
|
61
|
+
def next_symbol
|
62
|
+
@next_symbol ||= dotted_item.next_symbol
|
63
63
|
end
|
64
64
|
|
65
65
|
# Return the non-terminal symbol at the left-hand side of the production
|
66
66
|
# @return [Syntax::GrmSymbol]
|
67
67
|
# The non-terminal symbol at left side of production.
|
68
|
-
def lhs
|
69
|
-
|
68
|
+
def lhs
|
69
|
+
dotted_item.lhs
|
70
70
|
end
|
71
71
|
end # class
|
72
72
|
end # module
|
@@ -5,7 +5,7 @@ require_relative 'vertex'
|
|
5
5
|
module Rley # This module is used as a namespace
|
6
6
|
module GFG # This module is used as a namespace
|
7
7
|
# Abstract class.
|
8
|
-
# Represents a specialized vertex in a grammar flow graph
|
8
|
+
# Represents a specialized vertex in a grammar flow graph
|
9
9
|
# that is associated to a given non-terminal symbol and
|
10
10
|
# that may have in-degree or out-degree > 1
|
11
11
|
# Responsibilities (in addition to inherited ones):
|
@@ -14,20 +14,20 @@ module Rley # This module is used as a namespace
|
|
14
14
|
# The non-terminal symbol associated to the vertex
|
15
15
|
# @return [Syntax::NonTerminal]
|
16
16
|
attr_reader :non_terminal
|
17
|
-
|
17
|
+
|
18
18
|
# Constructor to specialize in subclasses.
|
19
19
|
# @param aNonTerminal [Syntax::NonTerminal]
|
20
20
|
def initialize(aNonTerminal)
|
21
21
|
super()
|
22
22
|
@non_terminal = aNonTerminal
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
protected
|
26
26
|
|
27
27
|
# Validation method for adding an outgoing edge to the vertex.
|
28
28
|
# A start vertex may accept an indegree and outdegree greater than one
|
29
29
|
def check_add_edge(anEdge)
|
30
|
-
|
30
|
+
anEdge
|
31
31
|
end
|
32
32
|
end # class
|
33
33
|
end # module
|
data/lib/rley/gfg/scan_edge.rb
CHANGED
@@ -12,12 +12,12 @@ module Rley # This module is used as a namespace
|
|
12
12
|
attr_reader :nonterminal
|
13
13
|
|
14
14
|
def initialize(thePredecessor, theSuccessor)
|
15
|
-
|
15
|
+
super(nil, theSuccessor)
|
16
16
|
@nonterminal = thePredecessor.next_symbol
|
17
17
|
thePredecessor.shortcut = self
|
18
18
|
end
|
19
19
|
|
20
|
-
def to_s
|
20
|
+
def to_s
|
21
21
|
" -#{nonterminal}-> #{successor.label}"
|
22
22
|
end
|
23
23
|
end # class
|
@@ -5,19 +5,15 @@ require_relative 'non_terminal_vertex'
|
|
5
5
|
module Rley # This module is used as a namespace
|
6
6
|
module GFG # This module is used as a namespace
|
7
7
|
# TODO: change definition.
|
8
|
-
# Represents a specialized vertex in a grammar flow graph
|
8
|
+
# Represents a specialized vertex in a grammar flow graph
|
9
9
|
# that is associated to a given non-terminal symbol.
|
10
10
|
# Responsibilities (in addition to inherited ones):
|
11
11
|
# - Know its related non-terminal symbol
|
12
12
|
class StartVertex < NonTerminalVertex
|
13
|
-
def initialize(aNonTerminal)
|
14
|
-
super(aNonTerminal)
|
15
|
-
end
|
16
|
-
|
17
13
|
# @return [String]
|
18
|
-
def label
|
19
|
-
|
20
|
-
end
|
14
|
+
def label
|
15
|
+
".#{non_terminal}"
|
16
|
+
end
|
21
17
|
end # class
|
22
18
|
end # module
|
23
19
|
end # module
|
data/lib/rley/gfg/vertex.rb
CHANGED
@@ -10,60 +10,65 @@ module Rley # This module is used as a namespace
|
|
10
10
|
# The edges linking the successor vertices to this one.
|
11
11
|
# @return [Array<Edge>] The edge(s) linking this vertex to successor(s)
|
12
12
|
attr_reader :edges
|
13
|
-
|
13
|
+
|
14
|
+
# Return the object id in string format
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :oid_str
|
17
|
+
|
14
18
|
# Constructor to extend in subclasses.
|
15
|
-
def initialize
|
19
|
+
def initialize
|
16
20
|
@edges = []
|
21
|
+
@oid_str = object_id.to_s
|
17
22
|
end
|
18
|
-
|
19
|
-
#
|
20
|
-
# @param anEdge [Edge] the edge to be added.
|
21
|
-
def add_edge(anEdge)
|
22
|
-
arrow = check_add_edge(anEdge)
|
23
|
-
edges << arrow
|
24
|
-
end
|
25
|
-
|
26
|
-
# Determine if the vertex corresponds to an dotted item that has
|
23
|
+
|
24
|
+
# Determine if the vertex corresponds to an dotted item that has
|
27
25
|
# its dot at the end of a production (i.e. is a reduced item).
|
28
26
|
# @return [Boolean] true iff vertex corresponds to reduced item.
|
29
|
-
def complete?
|
30
|
-
|
27
|
+
def complete?
|
28
|
+
false # Default implementation
|
31
29
|
end
|
32
|
-
|
33
|
-
# Returns a string containing a human-readable representation of the
|
30
|
+
|
31
|
+
# Returns a string containing a human-readable representation of the
|
34
32
|
# vertex.
|
35
33
|
# @return [String]
|
36
|
-
def inspect
|
34
|
+
def inspect
|
37
35
|
result = +'#<'
|
38
36
|
result << selfie
|
39
37
|
edges.each { |e| result << e.inspect }
|
40
38
|
result << specific_inspect
|
41
39
|
result << '>'
|
42
|
-
|
43
|
-
|
40
|
+
|
41
|
+
result
|
44
42
|
end
|
45
|
-
|
46
|
-
# Returns a string containing a human-readable representation of the
|
43
|
+
|
44
|
+
# Returns a string containing a human-readable representation of the
|
47
45
|
# vertex without the edges.
|
48
|
-
# @return [String]
|
49
|
-
def selfie
|
46
|
+
# @return [String]
|
47
|
+
def selfie
|
50
48
|
result = +"#{self.class.name}:#{object_id}"
|
51
49
|
result << %( label="#{label}")
|
52
|
-
|
50
|
+
result
|
53
51
|
end
|
54
|
-
|
52
|
+
|
55
53
|
# Retrieve the grammar symbol before the dot.
|
56
54
|
# @return [GrmSymbol, NilClass] The symbol or otherwise nil.
|
57
|
-
def prev_symbol
|
58
|
-
|
59
|
-
end
|
60
|
-
|
55
|
+
def prev_symbol
|
56
|
+
nil # Default implementation
|
57
|
+
end
|
58
|
+
|
61
59
|
# Retrieve the grammar symbol after the dot.
|
62
|
-
# @return [GrmSymbol, NilClass] The symbol or otherwise nil.
|
63
|
-
def next_symbol
|
64
|
-
|
60
|
+
# @return [GrmSymbol, NilClass] The symbol or otherwise nil.
|
61
|
+
def next_symbol
|
62
|
+
nil # Default implementation
|
63
|
+
end
|
64
|
+
|
65
|
+
# Add an graph edge to this vertex.
|
66
|
+
# @param anEdge [Edge] the edge to be added.
|
67
|
+
def add_edge(anEdge)
|
68
|
+
arrow = check_add_edge(anEdge)
|
69
|
+
edges << arrow
|
65
70
|
end
|
66
|
-
|
71
|
+
|
67
72
|
protected
|
68
73
|
|
69
74
|
# Validation method for adding an outgoing edge to the vertex.
|
@@ -71,14 +76,13 @@ module Rley # This module is used as a namespace
|
|
71
76
|
# unless this method is overridden in subclasses
|
72
77
|
def check_add_edge(anEdge)
|
73
78
|
raise StandardError, 'At most one edge accepted' unless edges.empty?
|
74
|
-
|
75
|
-
|
79
|
+
|
80
|
+
anEdge
|
81
|
+
end
|
82
|
+
|
83
|
+
def specific_inspect
|
84
|
+
''
|
76
85
|
end
|
77
|
-
|
78
|
-
def specific_inspect()
|
79
|
-
return ''
|
80
|
-
end
|
81
|
-
|
82
86
|
end # class
|
83
87
|
end # module
|
84
88
|
end # module
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './notation/grammar_builder'
|
4
|
+
|
5
|
+
module Rley # Module used as a namespace
|
6
|
+
# Factory method.
|
7
|
+
# A grammar builder constructs a Rley grammar piece by piece
|
8
|
+
# from DSL instructions in a provided code block.
|
9
|
+
# @param aBlock [Proc] a code block
|
10
|
+
# @return [Rley::Notation::GrammarBuilder] An object that builds a grammar.
|
11
|
+
def self.grammar_builder(&aBlock)
|
12
|
+
Rley::Notation::GrammarBuilder.new(&aBlock)
|
13
|
+
end
|
14
|
+
end # module
|
15
|
+
|
16
|
+
# End of file
|
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module Rley # This module is used as a namespace
|
4
4
|
module Lexical # This module is used as a namespace
|
5
|
-
# A token range (also called an extent) represents an interval
|
5
|
+
# A token range (also called an extent) represents an interval
|
6
6
|
# of token positions that is matched by a given grammar symbol.
|
7
7
|
# For instance consider the expression E: 3 + 11,
|
8
8
|
# let's assume that the integer literal '3' is the fifth input token and
|
9
9
|
# that the '+' and '11' tokens are respectively at position 6 and 7;
|
10
10
|
# then the token range associated with E is [5, 7]
|
11
|
-
# While the parse tree/forest is being constructed the boundaries of the
|
11
|
+
# While the parse tree/forest is being constructed the boundaries of the
|
12
12
|
# token range can be temporarily undefined (= set to nil)
|
13
13
|
class TokenRange
|
14
14
|
# The index of the lower bound of token range
|
@@ -47,8 +47,8 @@ module Rley # This module is used as a namespace
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# true when both bounds aren't nil.
|
50
|
-
def bounded?
|
51
|
-
|
50
|
+
def bounded?
|
51
|
+
!(low.nil? || high.nil?)
|
52
52
|
end
|
53
53
|
|
54
54
|
# Conditional assign
|
@@ -73,8 +73,8 @@ module Rley # This module is used as a namespace
|
|
73
73
|
def to_string(_indentation)
|
74
74
|
low_text = low.nil? ? '?' : low.to_s
|
75
75
|
high_text = high.nil? ? '?' : high.to_s
|
76
|
-
|
77
|
-
|
76
|
+
|
77
|
+
"[#{low_text}, #{high_text}]"
|
78
78
|
end
|
79
79
|
|
80
80
|
private
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../parse_rep/ast_base_builder'
|
4
|
+
require_relative '../engine'
|
5
|
+
require_relative 'all_notation_nodes'
|
6
|
+
|
7
|
+
module Rley
|
8
|
+
module Notation
|
9
|
+
# The purpose of ASTBuilder is to build piece by piece an AST
|
10
|
+
# (Abstract Syntax Tree) from a sequence of input tokens and
|
11
|
+
# visit events produced by walking over a GFGParsing object.
|
12
|
+
class ASTBuilder < Rley::ParseRep::ASTBaseBuilder
|
13
|
+
unless defined?(Name2special)
|
14
|
+
# Mapping Token name => operator | separator | delimiter characters
|
15
|
+
# @return [Hash{String => String}]
|
16
|
+
Name2special = {
|
17
|
+
'COMMA' => ',',
|
18
|
+
'ELLIPSIS' => '..',
|
19
|
+
'LEFT_BRACE' => '{',
|
20
|
+
'LEFT_PAREN' => '(',
|
21
|
+
'PLUS' => '+',
|
22
|
+
'QUESTION_MARK' => '?',
|
23
|
+
'RIGHT_BRACE' => '}',
|
24
|
+
'RIGHT_PAREN' => ')',
|
25
|
+
'STAR' => '*'
|
26
|
+
}.freeze
|
27
|
+
end
|
28
|
+
|
29
|
+
# Create a new AST builder instance.
|
30
|
+
# @param theTokens [Array<Rley::Lexical::Token>] The sequence of input tokens.
|
31
|
+
def initialize(theTokens)
|
32
|
+
super(theTokens)
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def terminal2node
|
38
|
+
Terminal2NodeClass
|
39
|
+
end
|
40
|
+
|
41
|
+
# Method override
|
42
|
+
def new_leaf_node(_production, _terminal, aTokenPosition, aToken)
|
43
|
+
Rley::PTree::TerminalNode.new(aToken, aTokenPosition)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Factory method for creating a parent node object.
|
47
|
+
# @param aProduction [Production] Production rule
|
48
|
+
# @param aRange [Range] Range of tokens matched by the rule
|
49
|
+
# @param theTokens [Array] The input tokens
|
50
|
+
# @param theChildren [Array] Children nodes (one per rhs symbol)
|
51
|
+
def new_parent_node(aProduction, aRange, theTokens, theChildren)
|
52
|
+
mth_name = method_name(aProduction.name)
|
53
|
+
if respond_to?(mth_name, true)
|
54
|
+
node = send(mth_name, aProduction, aRange, theTokens, theChildren)
|
55
|
+
else
|
56
|
+
# Default action...
|
57
|
+
node = case aProduction.rhs.size
|
58
|
+
when 0
|
59
|
+
return_epsilon(aRange, theTokens, theChildren)
|
60
|
+
when 1
|
61
|
+
return_first_child(aRange, theTokens, theChildren)
|
62
|
+
else
|
63
|
+
node = Rley::PTree::NonTerminalNode.new(aProduction.lhs, aRange)
|
64
|
+
theChildren&.reverse_each do |child|
|
65
|
+
node.add_subnode(child) if child
|
66
|
+
end
|
67
|
+
|
68
|
+
node
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
node
|
73
|
+
end
|
74
|
+
|
75
|
+
# Return the AST node corresponding to the second symbol in the rhs
|
76
|
+
def reduce_to_2nd_symbol(_production, _range, _tokens, theChildren)
|
77
|
+
theChildren[1]
|
78
|
+
end
|
79
|
+
|
80
|
+
#####################################
|
81
|
+
# SEMANTIC ACTIONS
|
82
|
+
#####################################
|
83
|
+
|
84
|
+
# rule('rhs' => 'member_seq').tag 'sequence'
|
85
|
+
def reduce_sequence(_production, _range, _tokens, theChildren)
|
86
|
+
if theChildren[0].size == 1
|
87
|
+
theChildren[0].first
|
88
|
+
else
|
89
|
+
SequenceNode.new(theChildren[0].first.position, theChildren[0], nil)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# rule('member_seq' => 'member_seq member').tag 'more_members'
|
94
|
+
def reduce_more_members(_production, _range, _tokens, theChildren)
|
95
|
+
theChildren[0] << theChildren[1]
|
96
|
+
end
|
97
|
+
|
98
|
+
# rule('member_seq' => 'member')
|
99
|
+
def reduce_one_member(_production, _range, _tokens, theChildren)
|
100
|
+
[theChildren[0]]
|
101
|
+
end
|
102
|
+
|
103
|
+
# rule('strait_member' => 'base_member annotation')
|
104
|
+
def reduce_annotated_member(_production, _range, _tokens, theChildren)
|
105
|
+
theChildren[0].annotation = theChildren[1]
|
106
|
+
|
107
|
+
theChildren[0]
|
108
|
+
end
|
109
|
+
|
110
|
+
# rule('base_member' => 'SYMBOL')
|
111
|
+
def reduce_symbol(_production, _range, _tokens, theChildren)
|
112
|
+
SymbolNode.new(theChildren[0].token.position, theChildren[0].token.lexeme)
|
113
|
+
end
|
114
|
+
|
115
|
+
# rule('base_member' => 'LEFT_PAREN member_seq RIGHT_PAREN')
|
116
|
+
def reduce_grouping(_production, _range, tokens, theChildren)
|
117
|
+
if theChildren[1].size == 1
|
118
|
+
theChildren[1].first
|
119
|
+
else
|
120
|
+
rank = theChildren[0].range.high
|
121
|
+
pos = tokens[rank].position
|
122
|
+
GroupingNode.new(pos, theChildren[1], nil)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# rule('quantified_member' => 'base_member quantifier')
|
127
|
+
def reduce_quantified_member(_production, _range, _tokens, theChildren)
|
128
|
+
theChildren[0].repetition = theChildren[1]
|
129
|
+
theChildren[0]
|
130
|
+
end
|
131
|
+
|
132
|
+
# rule('quantifier' => 'QUESTION_MARK')
|
133
|
+
def reduce_question_mark(_production, _range, _tokens, _theChildren)
|
134
|
+
:zero_or_one
|
135
|
+
end
|
136
|
+
|
137
|
+
# rule('quantifier' => 'STAR')
|
138
|
+
def reduce_star(_production, _range, _tokens, _theChildren)
|
139
|
+
:zero_or_more
|
140
|
+
end
|
141
|
+
|
142
|
+
# rule('quantifier' => 'PLUS')
|
143
|
+
def reduce_plus(_production, _range, _tokens, _theChildren)
|
144
|
+
:one_or_more
|
145
|
+
end
|
146
|
+
|
147
|
+
# rule('annotation' => 'LEFT_BRACE mapping RIGHT_BRACE').tag ''
|
148
|
+
def reduce_annotation(_production, _range, _tokens, theChildren)
|
149
|
+
theChildren[1]
|
150
|
+
end
|
151
|
+
|
152
|
+
# rule('mapping' => 'mapping COMMA key_value')
|
153
|
+
def reduce_more_pairs(_production, _range, _tokens, theChildren)
|
154
|
+
hsh = theChildren[0]
|
155
|
+
hsh[theChildren[2].first] = theChildren[2].last
|
156
|
+
|
157
|
+
hsh
|
158
|
+
end
|
159
|
+
|
160
|
+
# rule('mapping' => 'key_value').tag 'one_pair'
|
161
|
+
def reduce_one_pair(_production, _range, _tokens, theChildren)
|
162
|
+
{ theChildren[0].first => theChildren[0].last }
|
163
|
+
end
|
164
|
+
|
165
|
+
# rule('key_value' => 'KEY value')
|
166
|
+
def reduce_raw_pair(_production, _range, _tokens, theChildren)
|
167
|
+
key = theChildren[0].token.lexeme
|
168
|
+
value = if theChildren[1].kind_of?(Rley::PTree::TerminalNode)
|
169
|
+
theChildren[1].token.lexeme
|
170
|
+
else
|
171
|
+
theChildren[1]
|
172
|
+
end
|
173
|
+
[key, value]
|
174
|
+
end
|
175
|
+
|
176
|
+
# rule('range' => 'INT_LIT ELLIPSIS INT_LIT')
|
177
|
+
def reduce_bound_range(_production, _range, _tokens, theChildren)
|
178
|
+
low = theChildren[0].token.lexeme
|
179
|
+
high = theChildren[2].token.lexeme
|
180
|
+
case [low, high]
|
181
|
+
when ['0', '1']
|
182
|
+
:zero_or_one
|
183
|
+
when ['1', '1']
|
184
|
+
:exactly_one
|
185
|
+
else
|
186
|
+
Range.new(low.to_i, high.to_i)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end # class
|
190
|
+
end # module
|
191
|
+
end # module
|