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/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
|