rley 0.1.12 → 0.2.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 +8 -8
- data/CHANGELOG.md +9 -0
- data/examples/parsers/parsing_L0.rb +125 -0
- data/examples/parsers/parsing_b_expr.rb +84 -84
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/formatter/json.rb +4 -0
- data/lib/rley/parser/chart.rb +12 -0
- data/lib/rley/parser/parse_state_tracker.rb +55 -0
- data/lib/rley/parser/parse_tree_builder.rb +181 -0
- data/lib/rley/parser/parsing.rb +92 -55
- data/lib/rley/ptree/parse_tree.rb +3 -86
- data/lib/rley/ptree/token_range.rb +2 -0
- data/lib/rley/syntax/grammar.rb +6 -0
- data/lib/rley/syntax/grammar_builder.rb +1 -1
- data/spec/rley/formatter/json_spec.rb +2 -2
- data/spec/rley/parser/chart_spec.rb +5 -1
- data/spec/rley/parser/parse_tree_builder_spec.rb +179 -0
- data/spec/rley/parser/parsing_spec.rb +83 -9
- data/spec/rley/ptree/parse_tree_spec.rb +7 -60
- data/spec/rley/ptree/token_range_spec.rb +1 -0
- data/spec/rley/syntax/grammar_spec.rb +4 -0
- metadata +7 -2
@@ -19,7 +19,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
19
19
|
describe Parsing do
|
20
20
|
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
21
21
|
include GrammarBExprHelper # Mix-in with builder for simple expressions
|
22
|
-
|
22
|
+
|
23
23
|
# Grammar 1: A very simple language
|
24
24
|
# S ::= A.
|
25
25
|
# A ::= "a" A "c".
|
@@ -48,7 +48,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
48
48
|
|
49
49
|
|
50
50
|
let(:start_dotted_rule) { DottedItem.new(prod_S, 0) }
|
51
|
-
|
51
|
+
|
52
52
|
# Default instantiation rule
|
53
53
|
subject { Parsing.new(start_dotted_rule, grm1_tokens) }
|
54
54
|
|
@@ -116,26 +116,30 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
116
116
|
expect(new_state.dotted_rule).to eq(item1)
|
117
117
|
expect(new_state.origin).to eq(0)
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
end # context
|
121
|
-
|
121
|
+
|
122
122
|
context 'Parse tree building:' do
|
123
123
|
let(:sample_grammar1) do
|
124
124
|
builder = grammar_abc_builder
|
125
125
|
builder.grammar
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
let(:token_seq1) do
|
129
129
|
%w(a a b c c).map do |letter|
|
130
130
|
Token.new(letter, sample_grammar1.name2symbol[letter])
|
131
131
|
end
|
132
132
|
end
|
133
|
-
|
133
|
+
|
134
134
|
let(:b_expr_grammar) do
|
135
135
|
builder = grammar_expr_builder
|
136
136
|
builder.grammar
|
137
137
|
end
|
138
138
|
|
139
|
+
def grm_symbol(aSymbolName)
|
140
|
+
b_expr_grammar.name2symbol[aSymbolName]
|
141
|
+
end
|
142
|
+
|
139
143
|
|
140
144
|
it 'should build the parse tree for a simple non-ambiguous grammar' do
|
141
145
|
parser = EarleyParser.new(sample_grammar1)
|
@@ -143,16 +147,86 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
143
147
|
ptree = instance.parse_tree
|
144
148
|
expect(ptree).to be_kind_of(PTree::ParseTree)
|
145
149
|
end
|
146
|
-
|
150
|
+
|
147
151
|
it 'should build the parse tree for a simple expression grammar' do
|
148
152
|
parser = EarleyParser.new(b_expr_grammar)
|
149
153
|
tokens = expr_tokenizer('2 + 3 * 4', b_expr_grammar)
|
150
154
|
instance = parser.parse(tokens)
|
151
155
|
ptree = instance.parse_tree
|
152
156
|
expect(ptree).to be_kind_of(PTree::ParseTree)
|
157
|
+
|
158
|
+
# Expect parse tree:
|
159
|
+
# P[0, 5]
|
160
|
+
# +- S[0, 5]
|
161
|
+
# +- S[0, 1]
|
162
|
+
# +- M[0, 1]
|
163
|
+
# +- T[0, 1]
|
164
|
+
# +- integer(2)[0, 1]
|
165
|
+
# +- +[?, ?]
|
166
|
+
# +- M[2, 5]
|
167
|
+
expect(ptree.root.symbol). to eq(grm_symbol('P'))
|
168
|
+
expect(ptree.root.range). to eq([0, 5])
|
169
|
+
expect(ptree.root.children.size). to eq(1)
|
170
|
+
|
171
|
+
node = ptree.root.children[0] # S
|
172
|
+
expect(node.symbol). to eq(grm_symbol('S'))
|
173
|
+
expect(node.range). to eq([0, 5])
|
174
|
+
expect(node.children.size). to eq(3)
|
175
|
+
|
176
|
+
(node_s, node_plus, node_m) = node.children
|
177
|
+
expect(node_s.symbol).to eq(grm_symbol('S'))
|
178
|
+
expect(node_s.range).to eq({low: 0, high: 1})
|
179
|
+
expect(node_s.children.size).to eq(1)
|
180
|
+
expect(node_plus.symbol).to eq(grm_symbol('+'))
|
181
|
+
expect(node_plus.range).to eq({low: 0, high: 1}) # TODO: fix this
|
182
|
+
expect(node_plus.token.lexeme). to eq('+')
|
183
|
+
expect(node_m.symbol).to eq(grm_symbol('M'))
|
184
|
+
expect(node_m.range).to eq({low: 2, high: 5})
|
185
|
+
expect(node_m.children.size).to eq(3)
|
186
|
+
|
187
|
+
node = node_s.children[0] # M
|
188
|
+
expect(node.symbol).to eq(grm_symbol('M'))
|
189
|
+
expect(node.range).to eq([0, 1])
|
190
|
+
expect(node.children.size).to eq(1)
|
191
|
+
|
192
|
+
node = node.children[0] # T
|
193
|
+
expect(node.symbol).to eq(grm_symbol('T'))
|
194
|
+
expect(node.range).to eq([0, 1])
|
195
|
+
expect(node.children.size).to eq(1)
|
196
|
+
|
197
|
+
node = node.children[0] # integer(2)
|
198
|
+
expect(node.symbol).to eq(grm_symbol('integer'))
|
199
|
+
expect(node.range).to eq([0, 1])
|
200
|
+
expect(node.token.lexeme).to eq('2')
|
201
|
+
|
202
|
+
(node_m2, node_star, node_t3) = node_m.children
|
203
|
+
expect(node_m2.symbol).to eq(grm_symbol('M'))
|
204
|
+
expect(node_m2.range).to eq([2, 3])
|
205
|
+
expect(node_m2.children.size).to eq(1)
|
206
|
+
|
207
|
+
node_t2 = node_m2.children[0] # T
|
208
|
+
expect(node_t2.symbol).to eq(grm_symbol('T'))
|
209
|
+
expect(node_t2.range).to eq([2, 3])
|
210
|
+
expect(node_t2.children.size).to eq(1)
|
211
|
+
|
212
|
+
node = node_t2.children[0] # integer(3)
|
213
|
+
expect(node.symbol).to eq(grm_symbol('integer'))
|
214
|
+
expect(node.range).to eq([2, 3])
|
215
|
+
expect(node.token.lexeme).to eq('3')
|
216
|
+
|
217
|
+
expect(node_star.symbol).to eq(grm_symbol('*'))
|
218
|
+
expect(node_star.range).to eq([2, 3]) # Fix this
|
219
|
+
expect(node_star.token.lexeme). to eq('*')
|
220
|
+
|
221
|
+
expect(node_t3.symbol).to eq(grm_symbol('T'))
|
222
|
+
expect(node_t3.range).to eq([4, 5])
|
223
|
+
expect(node_t3.children.size).to eq(1)
|
224
|
+
|
225
|
+
node = node_t3.children[0] # integer(4)
|
226
|
+
expect(node.symbol).to eq(grm_symbol('integer'))
|
227
|
+
expect(node.range).to eq([4, 5])
|
228
|
+
expect(node.token.lexeme).to eq('4')
|
153
229
|
end
|
154
|
-
|
155
|
-
|
156
230
|
end # context
|
157
231
|
end # describe
|
158
232
|
end # module
|
@@ -11,7 +11,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
11
11
|
describe ParseTree do
|
12
12
|
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
13
13
|
|
14
|
-
|
15
14
|
let(:sample_grammar) do
|
16
15
|
builder = grammar_abc_builder
|
17
16
|
builder.grammar
|
@@ -19,75 +18,23 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
19
18
|
|
20
19
|
let(:sample_prod) { sample_grammar.rules[0] }
|
21
20
|
let(:sample_range) { { low: 0, high: 5 } }
|
22
|
-
|
21
|
+
let(:sample_root) { ParseTreeNode.new(sample_prod.lhs, sample_range) }
|
22
|
+
|
23
|
+
subject do
|
24
|
+
ParseTree.new(sample_root)
|
25
|
+
end
|
23
26
|
|
24
27
|
context 'Initialization:' do
|
25
|
-
it 'should be created with a
|
26
|
-
|
27
|
-
expect(construction).not_to raise_error
|
28
|
+
it 'should be created with a root node' do
|
29
|
+
expect { ParseTree.new(sample_root) }.not_to raise_error
|
28
30
|
end
|
29
31
|
|
30
32
|
it 'should know its root node' do
|
31
33
|
its_root = subject.root
|
32
34
|
expect(its_root.symbol.name).to eq('S')
|
33
35
|
expect(its_root.range).to eq(sample_range)
|
34
|
-
expect(its_root.children.size).to eq(1)
|
35
|
-
expect(its_root.children[0].symbol.name).to eq('A')
|
36
|
-
expect(its_root.children[0].range).to eq(sample_range)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should know its current path' do
|
40
|
-
path = subject.current_path
|
41
|
-
|
42
|
-
# Given the tree:
|
43
|
-
# S[0,5]
|
44
|
-
# +- A[0,5] <- current node
|
45
|
-
# Expected path: [S[0,5], 0, A[0,5]]
|
46
|
-
expect(path.size).to eq(3)
|
47
|
-
expect(path[0]).to eq(subject.root)
|
48
|
-
expect(path[1]).to eq(0)
|
49
|
-
expect(path[2]).to eq(subject.root.children[0])
|
50
|
-
expect(path[2].range).to eq(sample_range)
|
51
36
|
end
|
52
37
|
end # context
|
53
|
-
|
54
|
-
context 'Provided service:' do
|
55
|
-
it 'should add children to current node' do
|
56
|
-
subject.add_children(sample_grammar.rules[1], sample_range)
|
57
|
-
|
58
|
-
# Given the tree:
|
59
|
-
# S[0,5]
|
60
|
-
# +- A[0,5]
|
61
|
-
# +-a[0,nil]
|
62
|
-
# +-A[nil, nil]
|
63
|
-
# +-c[nil, 5] <- current node
|
64
|
-
# Expected path: [S[0,5], 0, A[0,5], 2, c[nil, 5]]
|
65
|
-
path = subject.current_path
|
66
|
-
expect(path.size).to eq(5)
|
67
|
-
expect(path[3]).to eq(2)
|
68
|
-
expect(path[4].symbol.name).to eq('c')
|
69
|
-
expect(path[4].range.low).to be_nil
|
70
|
-
expect(path[4].range.high).to eq(5)
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'should step back to a previous sibling node' do
|
74
|
-
subject.add_children(sample_grammar.rules[1], sample_range)
|
75
|
-
subject.step_back(4)
|
76
|
-
# Expected tree:
|
77
|
-
# S[0,5]
|
78
|
-
# +- A[0,5]
|
79
|
-
# +-a[0,nil]
|
80
|
-
# +-A[nil, 4] <- current node
|
81
|
-
# +-c[4, 5]
|
82
|
-
# Expected path: [S[0,5], 0, A[0,5], 1, A[nil, 4]]
|
83
|
-
path = subject.current_path
|
84
|
-
expect(path.size).to eq(5)
|
85
|
-
expect(path[3]).to eq(1)
|
86
|
-
expect(path[4].symbol.name).to eq('A')
|
87
|
-
expect(path[4].range.low).to be_nil
|
88
|
-
expect(path[4].range.high).to eq(4)
|
89
|
-
end
|
90
|
-
end
|
91
38
|
end # describe
|
92
39
|
end # module
|
93
40
|
end # module
|
@@ -141,6 +141,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
141
141
|
it 'should know all its non-terminal symbols' do
|
142
142
|
expect(subject.non_terminals).to eq([nt_S, nt_A])
|
143
143
|
end
|
144
|
+
|
145
|
+
it 'should know its start production' do
|
146
|
+
expect(subject.start_production).to eq(prod_S)
|
147
|
+
end
|
144
148
|
end # context
|
145
149
|
|
146
150
|
context 'Provided services:' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rley
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.00
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- examples/grammars/grammar_L0.rb
|
104
104
|
- examples/parsers/parsing_abc.rb
|
105
105
|
- examples/parsers/parsing_b_expr.rb
|
106
|
+
- examples/parsers/parsing_L0.rb
|
106
107
|
- examples/recognizers/recognizer_abc.rb
|
107
108
|
- lib/rley.rb
|
108
109
|
- lib/rley/constants.rb
|
@@ -113,6 +114,8 @@ files:
|
|
113
114
|
- lib/rley/parser/dotted_item.rb
|
114
115
|
- lib/rley/parser/earley_parser.rb
|
115
116
|
- lib/rley/parser/parse_state.rb
|
117
|
+
- lib/rley/parser/parse_state_tracker.rb
|
118
|
+
- lib/rley/parser/parse_tree_builder.rb
|
116
119
|
- lib/rley/parser/parsing.rb
|
117
120
|
- lib/rley/parser/state_set.rb
|
118
121
|
- lib/rley/parser/token.rb
|
@@ -137,6 +140,7 @@ files:
|
|
137
140
|
- spec/rley/parser/dotted_item_spec.rb
|
138
141
|
- spec/rley/parser/earley_parser_spec.rb
|
139
142
|
- spec/rley/parser/parse_state_spec.rb
|
143
|
+
- spec/rley/parser/parse_tree_builder_spec.rb
|
140
144
|
- spec/rley/parser/parsing_spec.rb
|
141
145
|
- spec/rley/parser/state_set_spec.rb
|
142
146
|
- spec/rley/parser/token_spec.rb
|
@@ -195,6 +199,7 @@ test_files:
|
|
195
199
|
- spec/rley/parser/dotted_item_spec.rb
|
196
200
|
- spec/rley/parser/earley_parser_spec.rb
|
197
201
|
- spec/rley/parser/parse_state_spec.rb
|
202
|
+
- spec/rley/parser/parse_tree_builder_spec.rb
|
198
203
|
- spec/rley/parser/parsing_spec.rb
|
199
204
|
- spec/rley/parser/state_set_spec.rb
|
200
205
|
- spec/rley/parser/token_spec.rb
|