rley 0.5.14 → 0.6.00
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/CHANGELOG.md +12 -2
- data/README.md +29 -31
- data/examples/NLP/benchmark_pico_en.rb +34 -34
- data/examples/NLP/engtagger.rb +1 -1
- data/examples/NLP/nano_eng/nano_en_demo.rb +23 -28
- data/examples/NLP/nano_eng/nano_grammar.rb +1 -1
- data/examples/NLP/pico_en_demo.rb +28 -31
- data/examples/data_formats/JSON/json_ast_builder.rb +11 -70
- data/examples/data_formats/JSON/json_demo.rb +32 -14
- data/examples/data_formats/JSON/json_grammar.rb +1 -1
- data/examples/data_formats/JSON/json_lexer.rb +5 -11
- data/examples/general/SRL/lib/ast_builder.rb +5 -28
- data/examples/general/SRL/lib/tokenizer.rb +2 -5
- data/examples/general/SRL/spec/integration_spec.rb +12 -5
- data/examples/general/SRL/spec/tokenizer_spec.rb +13 -14
- data/examples/general/SRL/srl_demo.rb +16 -9
- data/examples/general/calc_iter1/calc_ast_builder.rb +29 -85
- data/examples/general/calc_iter1/calc_demo.rb +15 -6
- data/examples/general/calc_iter1/calc_lexer.rb +2 -5
- data/examples/general/calc_iter1/spec/calculator_spec.rb +18 -19
- data/examples/general/calc_iter2/calc_ast_builder.rb +9 -107
- data/examples/general/calc_iter2/calc_demo.rb +15 -8
- data/examples/general/calc_iter2/calc_lexer.rb +3 -5
- data/examples/general/calc_iter2/spec/calculator_spec.rb +18 -31
- data/lib/rley.rb +2 -1
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/engine.rb +122 -0
- data/lib/rley/parse_rep/ast_base_builder.rb +128 -0
- data/lib/rley/{parser → parse_rep}/cst_builder.rb +1 -1
- data/lib/rley/{parser → parse_rep}/parse_forest_builder.rb +1 -1
- data/lib/rley/{parser → parse_rep}/parse_forest_factory.rb +2 -2
- data/lib/rley/{parser → parse_rep}/parse_rep_creator.rb +3 -3
- data/lib/rley/{parser → parse_rep}/parse_tree_builder.rb +4 -4
- data/lib/rley/{parser → parse_rep}/parse_tree_factory.rb +1 -1
- data/lib/rley/parser/gfg_parsing.rb +16 -4
- data/spec/rley/engine_spec.rb +127 -0
- data/spec/rley/formatter/asciitree_spec.rb +11 -13
- data/spec/rley/formatter/bracket_notation_spec.rb +11 -13
- data/spec/rley/formatter/debug_spec.rb +13 -15
- data/spec/rley/formatter/json_spec.rb +10 -14
- data/spec/rley/{parser → parse_rep}/ambiguous_parse_spec.rb +3 -3
- data/spec/rley/{parser → parse_rep}/ast_builder_spec.rb +34 -83
- data/spec/rley/{parser → parse_rep}/cst_builder_spec.rb +3 -3
- data/spec/rley/{parser → parse_rep}/groucho_spec.rb +3 -3
- data/spec/rley/{parser → parse_rep}/parse_forest_builder_spec.rb +4 -4
- data/spec/rley/{parser → parse_rep}/parse_forest_factory_spec.rb +2 -2
- data/spec/rley/{parser → parse_rep}/parse_tree_factory_spec.rb +2 -2
- data/spec/rley/parse_tree_visitor_spec.rb +12 -15
- data/spec/rley/support/ast_builder.rb +403 -0
- data/spec/rley/support/grammar_arr_int_helper.rb +2 -2
- metadata +27 -28
- data/examples/data_formats/JSON/json_parser.rb +0 -46
- data/examples/general/SRL/lib/ast_building.rb +0 -20
- data/examples/general/SRL/lib/parser.rb +0 -26
- data/examples/general/calc_iter1/calc_parser.rb +0 -24
- data/examples/general/calc_iter2/ast_building.rb +0 -20
- data/examples/general/calc_iter2/calc_parser.rb +0 -24
@@ -3,7 +3,7 @@ require_relative 'parse_rep_creator'
|
|
3
3
|
require_relative 'cst_builder'
|
4
4
|
|
5
5
|
module Rley # This module is used as a namespace
|
6
|
-
module
|
6
|
+
module ParseRep # This module is used as a namespace
|
7
7
|
# Utility class that helps to create a ParseTree from
|
8
8
|
# a given Parsing object.
|
9
9
|
class ParseTreeFactory < ParseRepCreator
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require_relative 'gfg_chart'
|
2
2
|
require_relative 'error_reason'
|
3
3
|
require_relative 'parse_entry_tracker'
|
4
|
-
require_relative 'parse_forest_factory'
|
5
|
-
require_relative 'parse_tree_factory'
|
4
|
+
require_relative '../parse_rep/parse_forest_factory'
|
5
|
+
require_relative '../parse_rep/parse_tree_factory'
|
6
6
|
|
7
7
|
|
8
8
|
module Rley # This module is used as a namespace
|
@@ -177,7 +177,13 @@ module Rley # This module is used as a namespace
|
|
177
177
|
# Factory method. Builds a ParseForest from the parse result.
|
178
178
|
# @return [ParseForest]
|
179
179
|
def parse_forest()
|
180
|
-
|
180
|
+
msg = <<-END_MSG
|
181
|
+
Method Rley::Parser::GFGParsing.parse_forest is deprecated, call
|
182
|
+
Rley::Engine::to_pforest. It will be removed April 1st
|
183
|
+
or version 0.6.1 (whichever is first)
|
184
|
+
END_MSG
|
185
|
+
# $stderr.puts(msg)
|
186
|
+
factory = ParseRep::ParseForestFactory.new(self)
|
181
187
|
|
182
188
|
return factory.create
|
183
189
|
end
|
@@ -185,7 +191,13 @@ module Rley # This module is used as a namespace
|
|
185
191
|
# Factory method. Builds a ParseTree from the parse result.
|
186
192
|
# @return [ParseTree]
|
187
193
|
def parse_tree(aBuilder = nil)
|
188
|
-
|
194
|
+
msg = <<-END_MSG
|
195
|
+
Method Rley::Parser::GFGParsing.parse_tree is deprecated, call
|
196
|
+
Rley::Engine::to_ptree. It will be removed April 1st
|
197
|
+
or version 0.6.1 (whichever is first)
|
198
|
+
END_MSG
|
199
|
+
$stderr.puts(msg)
|
200
|
+
factory = ParseRep::ParseTreeFactory.new(self)
|
189
201
|
|
190
202
|
return factory.create(aBuilder)
|
191
203
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
require_relative '../../lib/rley/lexical/token'
|
5
|
+
require_relative '../../lib/rley/parse_rep/cst_builder'
|
6
|
+
require_relative '../../lib/rley/parse_tree_visitor'
|
7
|
+
|
8
|
+
# Load the class under test
|
9
|
+
require_relative '../../lib/rley/engine'
|
10
|
+
|
11
|
+
module Rley # Open this namespace to avoid module qualifier prefixes
|
12
|
+
describe Engine do
|
13
|
+
subject { Engine.new }
|
14
|
+
|
15
|
+
context 'Creation and initialization:' do
|
16
|
+
it 'could be created without argument' do
|
17
|
+
expect { Engine.new }.not_to raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'could be created with block argument' do
|
21
|
+
expect { Engine.new do |config|
|
22
|
+
config.parse_repr = :raw
|
23
|
+
end
|
24
|
+
}.not_to raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it "shouldn't have a link to a grammar yet" do
|
28
|
+
expect(subject.grammar).to be_nil
|
29
|
+
end
|
30
|
+
end # context
|
31
|
+
|
32
|
+
context 'Grammar building:' do
|
33
|
+
it 'should build grammar' do
|
34
|
+
subject.build_grammar do
|
35
|
+
add_terminals('a', 'b', 'c')
|
36
|
+
add_production('S' => ['A'])
|
37
|
+
add_production('A' => %w[a A c])
|
38
|
+
add_production('A' => ['b'])
|
39
|
+
end
|
40
|
+
|
41
|
+
expect(subject.grammar).to be_kind_of(Rley::Syntax::Grammar)
|
42
|
+
expect(subject.grammar.rules.size).to eq(3)
|
43
|
+
end
|
44
|
+
end # context
|
45
|
+
|
46
|
+
class ABCTokenizer
|
47
|
+
# Constructor
|
48
|
+
def initialize(someText)
|
49
|
+
@input = someText.dup
|
50
|
+
end
|
51
|
+
|
52
|
+
def each()
|
53
|
+
lexemes = @input.scan(/\S/)
|
54
|
+
lexemes.each do |ch|
|
55
|
+
if ch =~ /[abc]/
|
56
|
+
yield Rley::Lexical::Token.new(ch, ch)
|
57
|
+
else
|
58
|
+
raise StandardError, "Invalid character #{ch}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end # class
|
63
|
+
|
64
|
+
# Utility method. Ensure that the engine
|
65
|
+
# has the defnition of a sample grammar
|
66
|
+
def add_sample_grammar(anEngine)
|
67
|
+
anEngine.build_grammar do
|
68
|
+
add_terminals('a', 'b', 'c')
|
69
|
+
add_production('S' => ['A'])
|
70
|
+
add_production('A' => %w[a A c])
|
71
|
+
add_production('A' => ['b'])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'Parsing:' do
|
76
|
+
subject do
|
77
|
+
instance = Engine.new
|
78
|
+
add_sample_grammar(instance)
|
79
|
+
instance
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should parse a stream of tokens' do
|
83
|
+
sample_text = 'a a b c c'
|
84
|
+
tokenizer = ABCTokenizer.new(sample_text)
|
85
|
+
result = subject.parse(tokenizer)
|
86
|
+
expect(result).to be_success
|
87
|
+
end
|
88
|
+
end # context
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
context 'Parse tree manipulation:' do
|
93
|
+
subject do
|
94
|
+
instance = Engine.new
|
95
|
+
add_sample_grammar(instance)
|
96
|
+
instance
|
97
|
+
end
|
98
|
+
|
99
|
+
let(:sample_tokenizer) do
|
100
|
+
sample_text = 'a a b c c'
|
101
|
+
ABCTokenizer.new(sample_text)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should build default parse trees' do
|
105
|
+
raw_result = subject.parse(sample_tokenizer)
|
106
|
+
ptree = subject.convert(raw_result)
|
107
|
+
expect(ptree).to be_kind_of(PTree::ParseTree)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should build custom parse trees' do
|
111
|
+
# Cheating: we point to default tree builder (CST)
|
112
|
+
subject.configuration.repr_builder = ParseRep::CSTBuilder
|
113
|
+
raw_result = subject.parse(sample_tokenizer)
|
114
|
+
ptree = subject.convert(raw_result)
|
115
|
+
expect(ptree).to be_kind_of(PTree::ParseTree)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should provide a parse visitor' do
|
119
|
+
raw_result = subject.parse(sample_tokenizer)
|
120
|
+
ptree = subject.to_ptree(raw_result)
|
121
|
+
visitor = subject.ptree_visitor(ptree)
|
122
|
+
expect(visitor).to be_kind_of(ParseTreeVisitor)
|
123
|
+
end
|
124
|
+
end # context
|
125
|
+
end # describe
|
126
|
+
end # module
|
127
|
+
|
@@ -6,18 +6,20 @@ require_relative '../../../lib/rley/lexical/token'
|
|
6
6
|
require_relative '../../../lib/rley/parser/gfg_earley_parser'
|
7
7
|
require_relative '../../../lib/rley/ptree/parse_tree'
|
8
8
|
require_relative '../../../lib/rley/parse_tree_visitor'
|
9
|
+
require_relative '../../../lib/rley/engine'
|
9
10
|
# Load the class under test
|
10
11
|
require_relative '../../../lib/rley/formatter/asciitree'
|
11
12
|
|
12
13
|
module Rley # Re-open the module to get rid of qualified names
|
13
14
|
module Formatter
|
14
15
|
describe Asciitree do
|
15
|
-
include GrammarABCHelper # Mix-in module for grammar abc
|
16
16
|
|
17
17
|
# Factory method. Build a production with the given sequence
|
18
18
|
# of symbols as its rhs.
|
19
19
|
let(:grammar_abc) do
|
20
|
-
|
20
|
+
sandbox = Object.new
|
21
|
+
sandbox.extend(GrammarABCHelper)
|
22
|
+
builder = sandbox.grammar_abc_builder
|
21
23
|
builder.grammar
|
22
24
|
end
|
23
25
|
|
@@ -27,15 +29,9 @@ module Rley # Re-open the module to get rid of qualified names
|
|
27
29
|
let(:c_) { grammar_abc.name2symbol['c'] }
|
28
30
|
|
29
31
|
# Helper method that mimicks the output of a tokenizer
|
30
|
-
# for the language specified by
|
32
|
+
# for the language specified by grammar_abc
|
31
33
|
let(:grm_abc_tokens1) do
|
32
|
-
[
|
33
|
-
Lexical::Token.new('a', a_),
|
34
|
-
Lexical::Token.new('a', a_),
|
35
|
-
Lexical::Token.new('b', b_),
|
36
|
-
Lexical::Token.new('c', c_),
|
37
|
-
Lexical::Token.new('c', c_)
|
38
|
-
]
|
34
|
+
%w[a a b c c].map { |ch| Lexical::Token.new(ch, ch) }
|
39
35
|
end
|
40
36
|
|
41
37
|
# Factory method that builds a sample parse tree.
|
@@ -51,9 +47,11 @@ module Rley # Re-open the module to get rid of qualified names
|
|
51
47
|
# +- c[4,5]
|
52
48
|
# Capital letters represent non-terminal nodes
|
53
49
|
let(:grm_abc_ptree1) do
|
54
|
-
|
55
|
-
|
56
|
-
parse_result.
|
50
|
+
engine = Rley::Engine.new
|
51
|
+
engine.use_grammar(grammar_abc)
|
52
|
+
parse_result = engine.parse(grm_abc_tokens1)
|
53
|
+
ptree = engine.convert(parse_result)
|
54
|
+
ptree
|
57
55
|
end
|
58
56
|
|
59
57
|
let(:destination) { StringIO.new('', 'w') }
|
@@ -6,18 +6,20 @@ require_relative '../../../lib/rley/lexical/token'
|
|
6
6
|
require_relative '../../../lib/rley/parser/gfg_earley_parser'
|
7
7
|
require_relative '../../../lib/rley/ptree/parse_tree'
|
8
8
|
require_relative '../../../lib/rley/parse_tree_visitor'
|
9
|
+
require_relative '../../../lib/rley/engine'
|
9
10
|
# Load the class under test
|
10
11
|
require_relative '../../../lib/rley/formatter/bracket_notation'
|
11
12
|
|
12
13
|
module Rley # Re-open the module to get rid of qualified names
|
13
14
|
module Formatter
|
14
15
|
describe BracketNotation do
|
15
|
-
include GrammarABCHelper # Mix-in module for grammar abc
|
16
16
|
|
17
17
|
# Factory method. Build a production with the given sequence
|
18
18
|
# of symbols as its rhs.
|
19
19
|
let(:grammar_abc) do
|
20
|
-
|
20
|
+
sandbox = Object.new
|
21
|
+
sandbox.extend(GrammarABCHelper)
|
22
|
+
builder = sandbox.grammar_abc_builder
|
21
23
|
builder.grammar
|
22
24
|
end
|
23
25
|
|
@@ -27,15 +29,9 @@ module Rley # Re-open the module to get rid of qualified names
|
|
27
29
|
let(:c_) { grammar_abc.name2symbol['c'] }
|
28
30
|
|
29
31
|
# Helper method that mimicks the output of a tokenizer
|
30
|
-
# for the language specified by
|
32
|
+
# for the language specified by grammar_abc
|
31
33
|
let(:grm_abc_tokens1) do
|
32
|
-
[
|
33
|
-
Lexical::Token.new('a', a_),
|
34
|
-
Lexical::Token.new('a', a_),
|
35
|
-
Lexical::Token.new('b', b_),
|
36
|
-
Lexical::Token.new('c', c_),
|
37
|
-
Lexical::Token.new('c', c_)
|
38
|
-
]
|
34
|
+
%w[a a b c c].map { |ch| Lexical::Token.new(ch, ch) }
|
39
35
|
end
|
40
36
|
|
41
37
|
# Factory method that builds a sample parse tree.
|
@@ -51,9 +47,11 @@ module Rley # Re-open the module to get rid of qualified names
|
|
51
47
|
# +- c[4,5]
|
52
48
|
# Capital letters represent non-terminal nodes
|
53
49
|
let(:grm_abc_ptree1) do
|
54
|
-
|
55
|
-
|
56
|
-
parse_result.
|
50
|
+
engine = Rley::Engine.new
|
51
|
+
engine.use_grammar(grammar_abc)
|
52
|
+
parse_result = engine.parse(grm_abc_tokens1)
|
53
|
+
ptree = engine.convert(parse_result)
|
54
|
+
ptree
|
57
55
|
end
|
58
56
|
|
59
57
|
let(:destination) { StringIO.new('', 'w') }
|
@@ -6,18 +6,20 @@ require_relative '../../../lib/rley/lexical/token'
|
|
6
6
|
require_relative '../../../lib/rley/parser/gfg_earley_parser'
|
7
7
|
require_relative '../../../lib/rley/ptree/parse_tree'
|
8
8
|
require_relative '../../../lib/rley/parse_tree_visitor'
|
9
|
+
require_relative '../../../lib/rley/engine'
|
9
10
|
# Load the class under test
|
10
11
|
require_relative '../../../lib/rley/formatter/debug'
|
11
12
|
|
12
13
|
module Rley # Re-open the module to get rid of qualified names
|
13
14
|
module Formatter
|
14
15
|
describe Debug do
|
15
|
-
include GrammarABCHelper # Mix-in module for grammar abc
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
# Factory method. Build a production with the given sequence
|
18
|
+
# of symbols as its rhs.
|
19
19
|
let(:grammar_abc) do
|
20
|
-
|
20
|
+
sandbox = Object.new
|
21
|
+
sandbox.extend(GrammarABCHelper)
|
22
|
+
builder = sandbox.grammar_abc_builder
|
21
23
|
builder.grammar
|
22
24
|
end
|
23
25
|
|
@@ -27,15 +29,9 @@ module Rley # Re-open the module to get rid of qualified names
|
|
27
29
|
let(:c_) { grammar_abc.name2symbol['c'] }
|
28
30
|
|
29
31
|
# Helper method that mimicks the output of a tokenizer
|
30
|
-
# for the language specified by
|
32
|
+
# for the language specified by grammar_abc
|
31
33
|
let(:grm_abc_tokens1) do
|
32
|
-
[
|
33
|
-
Lexical::Token.new('a', a_),
|
34
|
-
Lexical::Token.new('a', a_),
|
35
|
-
Lexical::Token.new('b', b_),
|
36
|
-
Lexical::Token.new('c', c_),
|
37
|
-
Lexical::Token.new('c', c_)
|
38
|
-
]
|
34
|
+
%w[a a b c c].map { |ch| Lexical::Token.new(ch, ch) }
|
39
35
|
end
|
40
36
|
|
41
37
|
# Factory method that builds a sample parse tree.
|
@@ -51,9 +47,11 @@ module Rley # Re-open the module to get rid of qualified names
|
|
51
47
|
# +- c[4,5]
|
52
48
|
# Capital letters represent non-terminal nodes
|
53
49
|
let(:grm_abc_ptree1) do
|
54
|
-
|
55
|
-
|
56
|
-
parse_result.
|
50
|
+
engine = Rley::Engine.new
|
51
|
+
engine.use_grammar(grammar_abc)
|
52
|
+
parse_result = engine.parse(grm_abc_tokens1)
|
53
|
+
ptree = engine.convert(parse_result)
|
54
|
+
ptree
|
57
55
|
end
|
58
56
|
|
59
57
|
let(:destination) { StringIO.new('', 'w') }
|
@@ -12,12 +12,12 @@ require_relative '../../../lib/rley/formatter/json'
|
|
12
12
|
module Rley # Re-open the module to get rid of qualified names
|
13
13
|
module Formatter
|
14
14
|
describe Json do
|
15
|
-
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
16
|
-
|
17
15
|
# Factory method. Build a production with the given sequence
|
18
16
|
# of symbols as its rhs.
|
19
17
|
let(:grammar_abc) do
|
20
|
-
|
18
|
+
sandbox = Object.new
|
19
|
+
sandbox.extend(GrammarABCHelper)
|
20
|
+
builder = sandbox.grammar_abc_builder
|
21
21
|
builder.grammar
|
22
22
|
end
|
23
23
|
|
@@ -27,15 +27,9 @@ module Rley # Re-open the module to get rid of qualified names
|
|
27
27
|
let(:c_) { grammar_abc.name2symbol['c'] }
|
28
28
|
|
29
29
|
# Helper method that mimicks the output of a tokenizer
|
30
|
-
# for the language specified by
|
30
|
+
# for the language specified by grammar_abc
|
31
31
|
let(:grm_abc_tokens1) do
|
32
|
-
[
|
33
|
-
Lexical::Token.new('a', a_),
|
34
|
-
Lexical::Token.new('a', a_),
|
35
|
-
Lexical::Token.new('b', b_),
|
36
|
-
Lexical::Token.new('c', c_),
|
37
|
-
Lexical::Token.new('c', c_)
|
38
|
-
]
|
32
|
+
%w[a a b c c].map { |ch| Lexical::Token.new(ch, ch) }
|
39
33
|
end
|
40
34
|
|
41
35
|
# Factory method that builds a sample parse tree.
|
@@ -51,9 +45,11 @@ module Rley # Re-open the module to get rid of qualified names
|
|
51
45
|
# +- c[4,5]
|
52
46
|
# Capital letters represent non-terminal nodes
|
53
47
|
let(:grm_abc_ptree1) do
|
54
|
-
|
55
|
-
|
56
|
-
parse_result.
|
48
|
+
engine = Rley::Engine.new
|
49
|
+
engine.use_grammar(grammar_abc)
|
50
|
+
parse_result = engine.parse(grm_abc_tokens1)
|
51
|
+
ptree = engine.convert(parse_result)
|
52
|
+
ptree
|
57
53
|
end
|
58
54
|
|
59
55
|
let(:destination) { StringIO.new('', 'w') }
|
@@ -8,10 +8,10 @@ require_relative '../support/expectation_helper'
|
|
8
8
|
require_relative '../support/grammar_ambig01_helper'
|
9
9
|
|
10
10
|
# Load the class under test
|
11
|
-
require_relative '../../../lib/rley/
|
11
|
+
require_relative '../../../lib/rley/parse_rep/parse_forest_builder'
|
12
12
|
|
13
13
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
14
|
-
module
|
14
|
+
module ParseRep
|
15
15
|
describe 'Coping with ambiguous grammar' do
|
16
16
|
include GrammarHelper # Mix-in with token factory method
|
17
17
|
include ExpectationHelper # Mix-in with expectation on parse entry sets
|
@@ -45,7 +45,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
45
45
|
end
|
46
46
|
|
47
47
|
before(:each) do
|
48
|
-
factory = ParseWalkerFactory.new
|
48
|
+
factory = Parser::ParseWalkerFactory.new
|
49
49
|
accept_entry = sentence_result.accepting_entry
|
50
50
|
accept_index = sentence_result.chart.last_index
|
51
51
|
@walker = factory.build_walker(accept_entry, accept_index, true)
|
@@ -2,7 +2,8 @@ require_relative '../../spec_helper'
|
|
2
2
|
|
3
3
|
require_relative '../../../lib/rley/parser/gfg_earley_parser'
|
4
4
|
require_relative '../../../lib/rley/parser/parse_walker_factory'
|
5
|
-
require_relative '../../../lib/rley/parser/parse_tree_builder'
|
5
|
+
# require_relative '../../../lib/rley/parser/parse_tree_builder'
|
6
|
+
require_relative '../../../lib/rley/parse_rep/ast_base_builder'
|
6
7
|
require_relative '../../../lib/rley/ptree/parse_tree'
|
7
8
|
|
8
9
|
require_relative '../support/expectation_helper'
|
@@ -11,7 +12,7 @@ require_relative '../support/grammar_arr_int_helper'
|
|
11
12
|
|
12
13
|
|
13
14
|
module Rley # This module is used as a namespace
|
14
|
-
module
|
15
|
+
module ParseRep # This module is used as a namespace
|
15
16
|
ArrayNode = Struct.new(:children) do
|
16
17
|
def initialize()
|
17
18
|
super
|
@@ -24,9 +25,9 @@ module Rley # This module is used as a namespace
|
|
24
25
|
end
|
25
26
|
|
26
27
|
IntegerNode = Struct.new(:value, :position) do
|
27
|
-
def initialize(
|
28
|
+
def initialize(integerToken, aPosition)
|
28
29
|
super
|
29
|
-
self.value =
|
30
|
+
self.value = integerToken.lexeme.to_i
|
30
31
|
self.position = aPosition
|
31
32
|
end
|
32
33
|
|
@@ -35,93 +36,43 @@ module Rley # This module is used as a namespace
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# The Builder pattern creates a complex object
|
43
|
-
# (say, a parse tree) from simpler objects (terminal and non-terminal
|
44
|
-
# nodes) and using a step by step approach.
|
45
|
-
class ASTBuilder < ParseTreeBuilder
|
46
|
-
protected
|
47
|
-
|
48
|
-
# Method to override
|
49
|
-
# Create a parse tree object with given
|
50
|
-
# node as root node.
|
51
|
-
def create_tree(aRootNode)
|
52
|
-
return Rley::PTree::ParseTree.new(aRootNode)
|
53
|
-
end
|
54
|
-
|
55
|
-
# Method to override
|
56
|
-
# Factory method for creating a node object for the given
|
57
|
-
# input token.
|
58
|
-
# @param terminal [Terminal] Terminal symbol associated with the token
|
59
|
-
# @param aTokenPosition [Integer] Position of token in the input stream
|
60
|
-
# @param aToken [Token] The input token
|
61
|
-
def new_leaf_node(_production, terminal, aTokenPosition, aToken)
|
62
|
-
if terminal.name == 'integer'
|
63
|
-
IntegerNode.new(aToken.lexeme, aTokenPosition)
|
64
|
-
else
|
65
|
-
PTree::TerminalNode.new(aToken, aTokenPosition)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Method to override.
|
70
|
-
# Factory method for creating a parent node object.
|
71
|
-
# @param aProduction [Production] Production rule
|
72
|
-
# @param aRange [Range] Range of tokens matched by the rule
|
73
|
-
# @param theTokens [Array] The input tokens
|
74
|
-
# @param theChildren [Array] Children nodes (one per rhs symbol)
|
75
|
-
def new_parent_node(aProduction, aRange, theTokens, theChildren)
|
76
|
-
node = case aProduction.name
|
77
|
-
when 'P_0'
|
78
|
-
reduce_P_0(aRange, theTokens, theChildren)
|
79
|
-
|
80
|
-
when 'arr_0'
|
81
|
-
reduce_arr_0(aRange, theTokens, theChildren)
|
82
|
-
|
83
|
-
when 'sequence_0'
|
84
|
-
reduce_sequence_0(aRange, theTokens, theChildren)
|
85
|
-
|
86
|
-
when 'sequence_1'
|
87
|
-
reduce_sequence_1(aRange, theTokens, theChildren)
|
88
|
-
|
89
|
-
when 'list_0'
|
90
|
-
reduce_list_0(aRange, theTokens, theChildren)
|
39
|
+
class ASTBuilder < ASTBaseBuilder
|
40
|
+
Terminal2NodeClass = {
|
41
|
+
'integer' => IntegerNode
|
42
|
+
}.freeze
|
91
43
|
|
92
|
-
|
93
|
-
|
94
|
-
else
|
95
|
-
err_msg = "Don't know production #{aProduction.name}"
|
96
|
-
raise StandardError, err_msg
|
97
|
-
end
|
98
|
-
|
99
|
-
return node
|
44
|
+
def terminal2node()
|
45
|
+
Terminal2NodeClass
|
100
46
|
end
|
101
47
|
|
102
|
-
def reduce_P_0(_range, _tokens, theChildren)
|
103
|
-
|
48
|
+
def reduce_P_0(_aProd, _range, _tokens, theChildren)
|
49
|
+
return_first_child(_range, _tokens, theChildren)
|
104
50
|
end
|
105
51
|
|
106
|
-
|
52
|
+
# rule 'arr' => %w([ sequence ])
|
53
|
+
def reduce_arr_0(_aProd, _range, _tokens, theChildren)
|
107
54
|
return theChildren[1]
|
108
55
|
end
|
109
56
|
|
110
|
-
|
111
|
-
|
57
|
+
# rule 'sequence' => ['list']
|
58
|
+
def reduce_sequence_0(_aProd, _range, _tokens, theChildren)
|
59
|
+
return_first_child(_range, _tokens, theChildren)
|
112
60
|
end
|
113
61
|
|
114
|
-
|
62
|
+
# rule 'sequence' => []
|
63
|
+
def reduce_sequence_1(_aProd, _range, _tokens, _children)
|
115
64
|
return ArrayNode.new
|
116
65
|
end
|
117
66
|
|
118
|
-
|
67
|
+
# rule 'list' => %w[list , integer]
|
68
|
+
def reduce_list_0(_aProd, _range, _tokens, theChildren)
|
119
69
|
node = theChildren[0]
|
120
70
|
node.children << theChildren[2]
|
121
71
|
return node
|
122
72
|
end
|
123
73
|
|
124
|
-
|
74
|
+
# rule 'list' => 'integer'
|
75
|
+
def reduce_list_1(_aProd, _range, _tokens, theChildren)
|
125
76
|
node = ArrayNode.new
|
126
77
|
node.children << theChildren[0]
|
127
78
|
return node
|
@@ -132,7 +83,7 @@ end # module
|
|
132
83
|
|
133
84
|
|
134
85
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
135
|
-
module
|
86
|
+
module ParseRep
|
136
87
|
describe ASTBuilder do
|
137
88
|
include ExpectationHelper # Mix-in with expectation on parse entry sets
|
138
89
|
include GrammarArrIntHelper # Mix-in for array of integers language
|
@@ -150,7 +101,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
150
101
|
|
151
102
|
def init_walker(theParser, theTokens)
|
152
103
|
result = theParser.parse(theTokens)
|
153
|
-
factory = ParseWalkerFactory.new
|
104
|
+
factory = Parser::ParseWalkerFactory.new
|
154
105
|
accept_entry = result.accepting_entry
|
155
106
|
accept_index = result.chart.last_index
|
156
107
|
@walker = factory.build_walker(accept_entry, accept_index)
|
@@ -236,15 +187,15 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
236
187
|
# Event: visit P => . arr | 0 0
|
237
188
|
# Event: visit .P | 0 0
|
238
189
|
|
239
|
-
it 'should accept a first visit event' do
|
240
|
-
stack = get_stack(subject)
|
190
|
+
# it 'should accept a first visit event' do
|
191
|
+
# stack = get_stack(subject)
|
241
192
|
|
242
|
-
next_event('visit P. | 0 7')
|
243
|
-
expect(stack.size).to eq(1)
|
244
|
-
# stack: [P[0, 7]]
|
245
|
-
expect(stack.last.range).to eq(create_range(0, 7))
|
246
|
-
expect(stack.last.children).to be_nil
|
247
|
-
end
|
193
|
+
# next_event('visit P. | 0 7')
|
194
|
+
# expect(stack.size).to eq(1)
|
195
|
+
# # stack: [P[0, 7]]
|
196
|
+
# expect(stack.last.range).to eq(create_range(0, 7))
|
197
|
+
# expect(stack.last.children).to be_nil
|
198
|
+
# end
|
248
199
|
|
249
200
|
it 'should build a tree for an empty array' do
|
250
201
|
stack = get_stack(subject)
|