rley 0.8.01 → 0.8.02

Sign up to get free protection for your applications and to get access to all the features.
@@ -51,7 +51,7 @@ module Rley # This module is used as a namespace
51
51
  result.chart[index].each do |entry|
52
52
  # Is entry of the form? [A => alpha . B beta, k]...
53
53
  next_symbol = entry.next_symbol
54
- if next_symbol&.kind_of?(Syntax::NonTerminal)
54
+ if next_symbol.kind_of?(Syntax::NonTerminal)
55
55
  # ...apply the Call rule
56
56
  call_rule(result, entry, index)
57
57
  end
@@ -55,14 +55,14 @@ module Rley # This module is used as a namespace
55
55
  new_symbs = build_symbols(Terminal, terminalSymbols)
56
56
  symbols.merge!(new_symbs)
57
57
  end
58
-
58
+
59
59
  # Add the given marker symbol to the grammar of the language
60
60
  # @param aMarkerSymbol [Syntax::Marker] A mazker symbol
61
- # @return [void]
61
+ # @return [void]
62
62
  def add_marker(aMarkerSymbol)
63
63
  new_symb = build_symbol(Marker, aMarkerSymbol)
64
64
  symbols[aMarkerSymbol.name] = new_symb
65
- end
65
+ end
66
66
 
67
67
  # Add a production rule in the grammar given one
68
68
  # key-value pair of the form: String => Array.
@@ -7,13 +7,13 @@ module Rley # This module is used as a namespace
7
7
  class MatchClosest
8
8
  # @return [Integer] index of constrained symbol to match
9
9
  attr_reader(:idx_symbol)
10
-
10
+
11
11
  # @return [String] name of closest preceding symbol to pair
12
12
  attr_reader(:closest_symb)
13
13
 
14
14
  # @return [NilClass, Array<Parser::ParseEntry>] set of entries with closest symbol
15
15
  attr_accessor(:entries)
16
-
16
+
17
17
  # @param aSymbolSeq [Rley::Syntax::SymbolSeq] a sequence of grammar symbols
18
18
  # @param idxSymbol [Integer] index of symbol
19
19
  # @param nameClosest [String] Terminal symbol name
@@ -21,18 +21,18 @@ module Rley # This module is used as a namespace
21
21
  @idx_symbol = valid_idx_symbol(idxSymbol, aSymbolSeq)
22
22
  @closest_symb = valid_name_closest(nameClosest)
23
23
  end
24
-
24
+
25
25
  private
26
-
26
+
27
27
  # Check that the provided index is within plausible bounds
28
28
  def valid_idx_symbol(idxSymbol, aSymbolSeq)
29
- bounds = 0 .. aSymbolSeq.size - 1
29
+ bounds = 0..aSymbolSeq.size - 1
30
30
  err_msg_outbound = 'Index of symbol out of bound'
31
31
  raise StandardError, err_msg_outbound unless bounds.include? idxSymbol
32
-
32
+
33
33
  idxSymbol
34
34
  end
35
-
35
+
36
36
  def valid_name_closest(nameClosest)
37
37
  nameClosest
38
38
  end
@@ -170,7 +170,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
170
170
  expect(val_prod.rhs.members[0].name).to eq('digit_plus')
171
171
  end
172
172
 
173
- it "should support optional grouping" do
173
+ it 'should support optional grouping' do
174
174
  instance = GrammarBuilder.new
175
175
  instance.add_terminals('EQUAL', 'IDENTIFIER', 'VAR')
176
176
 
@@ -199,7 +199,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
199
199
  expect(p2.name).to eq('_qmark_none')
200
200
  end
201
201
 
202
- it "should support grouping with star modifier" do
202
+ it 'should support grouping with star modifier' do
203
203
  instance = GrammarBuilder.new
204
204
  instance.add_terminals('OR')
205
205
 
@@ -230,7 +230,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
230
230
  expect(p2.name).to eq('_star_none')
231
231
  end
232
232
 
233
- it "should support grouping with plus modifier" do
233
+ it 'should support grouping with plus modifier' do
234
234
  instance = GrammarBuilder.new
235
235
  instance.add_terminals('POINT TO SEMI_COLON')
236
236
 
@@ -261,7 +261,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
261
261
  expect(p2.name).to eq('_plus_one')
262
262
  end
263
263
 
264
- it "should support grouping with nested annotation" do
264
+ it 'should support grouping with nested annotation' do
265
265
  instance = GrammarBuilder.new
266
266
  instance.add_terminals('IF ELSE LPAREN RPAREN')
267
267
  st = "IF LPAREN expr RPAREN stmt (ELSE { match_closest: 'IF' } stmt)?"
@@ -281,7 +281,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
281
281
  expect(p0.rhs[0].name).to eq('ELSE')
282
282
  expect(p0.rhs[1].name).to eq('stmt')
283
283
  expect(p0.name).to eq('return_children')
284
- expect(p0.constraints.size). to eq(1)
284
+ expect(p0.constraints.size).to eq(1)
285
285
  expect(p0.constraints[0]).to be_kind_of(Syntax::MatchClosest)
286
286
  expect(p0.constraints[0].idx_symbol).to eq(0) # ELSE is on position 0
287
287
  expect(p0.constraints[0].closest_symb).to eq('IF')
@@ -299,4 +299,4 @@ module Rley # Open this namespace to avoid module qualifier prefixes
299
299
  end # module
300
300
  end # module
301
301
 
302
- # End of file
302
+ # End of file
@@ -1,184 +1,183 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../spec_helper' # Use the RSpec framework
4
-
5
- require_relative '../../../lib/rley/notation/ast_builder'
6
- # Load the class under test
7
- require_relative '../../../lib/rley/notation/parser'
8
-
9
- module Rley
10
- module Notation
11
- describe Parser do
12
- subject { Parser.new }
13
-
14
- # Utility method to walk towards deeply nested node
15
- # @param aNTNode [Rley::PTree::NonTerminalNode]
16
- # @param subnodePath[Array<Integer>] An Array of subnode indices
17
- def walk_subnodes(aNTNode, subnodePath)
18
- curr_node = aNTNode
19
- subnodePath.each do |index|
20
- curr_node = curr_node.subnodes[index]
21
- end
22
-
23
- curr_node
24
- end
25
-
26
- context 'Initialization:' do
27
- it 'should be initialized without argument' do
28
- expect { Parser.new }.not_to raise_error
29
- end
30
-
31
- it 'should have its parse engine initialized' do
32
- expect(subject.engine).to be_kind_of(Rley::Engine)
33
- end
34
- end # context
35
-
36
- context 'Parsing into CST:' do
37
- subject do
38
- instance = Parser.new
39
- instance.engine.configuration.repr_builder = Rley::ParseRep::CSTBuilder
40
-
41
- instance
42
- end
43
-
44
- it 'should parse single symbol names' do
45
- samples = %w[IF ifCondition statement]
46
-
47
- # One drawback od CSTs: they have a deeply nested structure
48
- samples.each do |source|
49
- ptree = subject.parse(source)
50
- expect(ptree.root).to be_kind_of(Rley::PTree::NonTerminalNode)
51
- expect(ptree.root.symbol.name).to eq('notation')
52
- expect(ptree.root.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
53
- expect(ptree.root.subnodes[0].symbol.name).to eq('rhs')
54
- expect(ptree.root.subnodes[0].subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
55
- member_seq = ptree.root.subnodes[0].subnodes[0]
56
- expect(member_seq.symbol.name).to eq('member_seq')
57
- expect(member_seq.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
58
- expect(member_seq.subnodes[0].symbol.name).to eq('member')
59
- expect(member_seq.subnodes[0].subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
60
- expect(member_seq.subnodes[0].subnodes[0].symbol.name).to eq('strait_member')
61
- strait_member = member_seq.subnodes[0].subnodes[0]
62
- expect(strait_member.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
63
- expect(strait_member.subnodes[0].symbol.name).to eq('base_member')
64
- expect(strait_member.subnodes[0].subnodes[0]).to be_kind_of(Rley::PTree::TerminalNode)
65
- expect(strait_member.subnodes[0].subnodes[0].token.lexeme).to eq(source)
66
- end
67
- end
68
-
69
- end # context
70
-
71
- context 'Parsing into AST:' do
72
- subject do
73
- instance = Parser.new
74
- instance.engine.configuration.repr_builder = ASTBuilder
75
-
76
- instance
77
- end
78
-
79
- it 'should parse single symbol names' do
80
- samples = %w[IF ifCondition statement]
81
-
82
- samples.each do |source|
83
- ptree = subject.parse(source)
84
- expect(ptree.root).to be_kind_of(SymbolNode)
85
- expect(ptree.root.name).to eq(source)
86
- expect(ptree.root.repetition).to eq(:exactly_one)
87
- end
88
- end
89
-
90
- it 'should parse a sequence of symbols' do
91
- sequence = 'INT_LIT ELLIPSIS INT_LIT'
92
-
93
- ptree = subject.parse(sequence)
94
- expect(ptree.root).to be_kind_of(SequenceNode)
95
- expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
96
- expect(ptree.root.subnodes[0].name).to eq('INT_LIT')
97
- expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
98
- expect(ptree.root.subnodes[1].name).to eq('ELLIPSIS')
99
- expect(ptree.root.subnodes[2]).to be_kind_of(SymbolNode)
100
- expect(ptree.root.subnodes[2].name).to eq('INT_LIT')
101
- end
102
-
103
- it 'should parse an optional symbol' do
104
- optional = 'member_seq?'
105
-
106
- ptree = subject.parse(optional)
107
- expect(ptree.root).to be_kind_of(SymbolNode)
108
- expect(ptree.root.name).to eq('member_seq')
109
- expect(ptree.root.repetition).to eq(:zero_or_one)
110
- end
111
-
112
- it 'should parse a symbol with a + modifier' do
113
- one_or_more = 'member+'
114
-
115
- ptree = subject.parse(one_or_more)
116
- expect(ptree.root).to be_kind_of(SymbolNode)
117
- expect(ptree.root.name).to eq('member')
118
- expect(ptree.root.repetition).to eq(:one_or_more)
119
- end
120
-
121
- it 'should parse a symbol with a * modifier' do
122
- zero_or_more = 'declaration* EOF'
123
-
124
- ptree = subject.parse(zero_or_more)
125
- expect(ptree.root).to be_kind_of(SequenceNode)
126
- expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
127
- expect(ptree.root.subnodes[0].name).to eq('declaration')
128
- expect(ptree.root.subnodes[0].repetition).to eq(:zero_or_more)
129
- expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
130
- expect(ptree.root.subnodes[1].name).to eq('EOF')
131
- expect(ptree.root.subnodes[1].repetition).to eq(:exactly_one)
132
- end
133
-
134
- it 'should parse a grouping with a modifier' do
135
- input = "IF ifCondition statement (ELSE statement)?"
136
-
137
- ptree = subject.parse(input)
138
- expect(ptree.root).to be_kind_of(SequenceNode)
139
- expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
140
- expect(ptree.root.subnodes[0].name).to eq('IF')
141
- expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
142
- expect(ptree.root.subnodes[1].name).to eq('ifCondition')
143
- expect(ptree.root.subnodes[2]).to be_kind_of(SymbolNode)
144
- expect(ptree.root.subnodes[2].name).to eq('statement')
145
- expect(ptree.root.subnodes[3]).to be_kind_of(SequenceNode)
146
- expect(ptree.root.subnodes[3].repetition).to eq(:zero_or_one)
147
- expect(ptree.root.subnodes[3].subnodes[0]).to be_kind_of(SymbolNode)
148
- expect(ptree.root.subnodes[3].subnodes[0].name).to eq('ELSE')
149
- expect(ptree.root.subnodes[3].subnodes[1]).to be_kind_of(SymbolNode)
150
- expect(ptree.root.subnodes[3].subnodes[1].name).to eq('statement')
151
- end
152
-
153
- it 'should parse an annotated symbol' do
154
- optional = 'member_seq{repeat: 0..1}'
155
-
156
- ptree = subject.parse(optional)
157
- expect(ptree.root).to be_kind_of(SymbolNode)
158
- expect(ptree.root.name).to eq('member_seq')
159
- expect(ptree.root.repetition).to eq(:zero_or_one)
160
- end
161
-
162
- it 'should parse a grouping with embedded annotation' do
163
- if_stmt = "IF ifCondition statement ( ELSE { match_closest: 'IF' } statement )?"
164
-
165
- ptree = subject.parse(if_stmt)
166
- expect(ptree.root).to be_kind_of(SequenceNode)
167
- expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
168
- expect(ptree.root.subnodes[0].name).to eq('IF')
169
- expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
170
- expect(ptree.root.subnodes[1].name).to eq('ifCondition')
171
- expect(ptree.root.subnodes[2]).to be_kind_of(SymbolNode)
172
- expect(ptree.root.subnodes[2].name).to eq('statement')
173
- optional = ptree.root.subnodes[3]
174
- expect(optional).to be_kind_of(SequenceNode)
175
- expect(optional.repetition).to eq(:zero_or_one)
176
- expect(optional.subnodes[0]).to be_kind_of(SymbolNode)
177
- expect(optional.subnodes[0].name).to eq('ELSE')
178
- expect(optional.subnodes[0].annotation).to eq({'match_closest' => 'IF'})
179
- expect(optional.subnodes[1].name).to eq('statement')
180
- end
181
- end # context
182
- end # describe
183
- end # module
184
- end # module
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper' # Use the RSpec framework
4
+
5
+ require_relative '../../../lib/rley/notation/ast_builder'
6
+ # Load the class under test
7
+ require_relative '../../../lib/rley/notation/parser'
8
+
9
+ module Rley
10
+ module Notation
11
+ describe Parser do
12
+ subject { Parser.new }
13
+
14
+ # Utility method to walk towards deeply nested node
15
+ # @param aNTNode [Rley::PTree::NonTerminalNode]
16
+ # @param subnodePath[Array<Integer>] An Array of subnode indices
17
+ def walk_subnodes(aNTNode, subnodePath)
18
+ curr_node = aNTNode
19
+ subnodePath.each do |index|
20
+ curr_node = curr_node.subnodes[index]
21
+ end
22
+
23
+ curr_node
24
+ end
25
+
26
+ context 'Initialization:' do
27
+ it 'should be initialized without argument' do
28
+ expect { Parser.new }.not_to raise_error
29
+ end
30
+
31
+ it 'should have its parse engine initialized' do
32
+ expect(subject.engine).to be_kind_of(Rley::Engine)
33
+ end
34
+ end # context
35
+
36
+ context 'Parsing into CST:' do
37
+ subject do
38
+ instance = Parser.new
39
+ instance.engine.configuration.repr_builder = Rley::ParseRep::CSTBuilder
40
+
41
+ instance
42
+ end
43
+
44
+ it 'should parse single symbol names' do
45
+ samples = %w[IF ifCondition statement]
46
+
47
+ # One drawback od CSTs: they have a deeply nested structure
48
+ samples.each do |source|
49
+ ptree = subject.parse(source)
50
+ expect(ptree.root).to be_kind_of(Rley::PTree::NonTerminalNode)
51
+ expect(ptree.root.symbol.name).to eq('notation')
52
+ expect(ptree.root.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
53
+ expect(ptree.root.subnodes[0].symbol.name).to eq('rhs')
54
+ expect(ptree.root.subnodes[0].subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
55
+ member_seq = ptree.root.subnodes[0].subnodes[0]
56
+ expect(member_seq.symbol.name).to eq('member_seq')
57
+ expect(member_seq.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
58
+ expect(member_seq.subnodes[0].symbol.name).to eq('member')
59
+ expect(member_seq.subnodes[0].subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
60
+ expect(member_seq.subnodes[0].subnodes[0].symbol.name).to eq('strait_member')
61
+ strait_member = member_seq.subnodes[0].subnodes[0]
62
+ expect(strait_member.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
63
+ expect(strait_member.subnodes[0].symbol.name).to eq('base_member')
64
+ expect(strait_member.subnodes[0].subnodes[0]).to be_kind_of(Rley::PTree::TerminalNode)
65
+ expect(strait_member.subnodes[0].subnodes[0].token.lexeme).to eq(source)
66
+ end
67
+ end
68
+ end # context
69
+
70
+ context 'Parsing into AST:' do
71
+ subject do
72
+ instance = Parser.new
73
+ instance.engine.configuration.repr_builder = ASTBuilder
74
+
75
+ instance
76
+ end
77
+
78
+ it 'should parse single symbol names' do
79
+ samples = %w[IF ifCondition statement]
80
+
81
+ samples.each do |source|
82
+ ptree = subject.parse(source)
83
+ expect(ptree.root).to be_kind_of(SymbolNode)
84
+ expect(ptree.root.name).to eq(source)
85
+ expect(ptree.root.repetition).to eq(:exactly_one)
86
+ end
87
+ end
88
+
89
+ it 'should parse a sequence of symbols' do
90
+ sequence = 'INT_LIT ELLIPSIS INT_LIT'
91
+
92
+ ptree = subject.parse(sequence)
93
+ expect(ptree.root).to be_kind_of(SequenceNode)
94
+ expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
95
+ expect(ptree.root.subnodes[0].name).to eq('INT_LIT')
96
+ expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
97
+ expect(ptree.root.subnodes[1].name).to eq('ELLIPSIS')
98
+ expect(ptree.root.subnodes[2]).to be_kind_of(SymbolNode)
99
+ expect(ptree.root.subnodes[2].name).to eq('INT_LIT')
100
+ end
101
+
102
+ it 'should parse an optional symbol' do
103
+ optional = 'member_seq?'
104
+
105
+ ptree = subject.parse(optional)
106
+ expect(ptree.root).to be_kind_of(SymbolNode)
107
+ expect(ptree.root.name).to eq('member_seq')
108
+ expect(ptree.root.repetition).to eq(:zero_or_one)
109
+ end
110
+
111
+ it 'should parse a symbol with a + modifier' do
112
+ one_or_more = 'member+'
113
+
114
+ ptree = subject.parse(one_or_more)
115
+ expect(ptree.root).to be_kind_of(SymbolNode)
116
+ expect(ptree.root.name).to eq('member')
117
+ expect(ptree.root.repetition).to eq(:one_or_more)
118
+ end
119
+
120
+ it 'should parse a symbol with a * modifier' do
121
+ zero_or_more = 'declaration* EOF'
122
+
123
+ ptree = subject.parse(zero_or_more)
124
+ expect(ptree.root).to be_kind_of(SequenceNode)
125
+ expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
126
+ expect(ptree.root.subnodes[0].name).to eq('declaration')
127
+ expect(ptree.root.subnodes[0].repetition).to eq(:zero_or_more)
128
+ expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
129
+ expect(ptree.root.subnodes[1].name).to eq('EOF')
130
+ expect(ptree.root.subnodes[1].repetition).to eq(:exactly_one)
131
+ end
132
+
133
+ it 'should parse a grouping with a modifier' do
134
+ input = 'IF ifCondition statement (ELSE statement)?'
135
+
136
+ ptree = subject.parse(input)
137
+ expect(ptree.root).to be_kind_of(SequenceNode)
138
+ expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
139
+ expect(ptree.root.subnodes[0].name).to eq('IF')
140
+ expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
141
+ expect(ptree.root.subnodes[1].name).to eq('ifCondition')
142
+ expect(ptree.root.subnodes[2]).to be_kind_of(SymbolNode)
143
+ expect(ptree.root.subnodes[2].name).to eq('statement')
144
+ expect(ptree.root.subnodes[3]).to be_kind_of(SequenceNode)
145
+ expect(ptree.root.subnodes[3].repetition).to eq(:zero_or_one)
146
+ expect(ptree.root.subnodes[3].subnodes[0]).to be_kind_of(SymbolNode)
147
+ expect(ptree.root.subnodes[3].subnodes[0].name).to eq('ELSE')
148
+ expect(ptree.root.subnodes[3].subnodes[1]).to be_kind_of(SymbolNode)
149
+ expect(ptree.root.subnodes[3].subnodes[1].name).to eq('statement')
150
+ end
151
+
152
+ it 'should parse an annotated symbol' do
153
+ optional = 'member_seq{repeat: 0..1}'
154
+
155
+ ptree = subject.parse(optional)
156
+ expect(ptree.root).to be_kind_of(SymbolNode)
157
+ expect(ptree.root.name).to eq('member_seq')
158
+ expect(ptree.root.repetition).to eq(:zero_or_one)
159
+ end
160
+
161
+ it 'should parse a grouping with embedded annotation' do
162
+ if_stmt = "IF ifCondition statement ( ELSE { match_closest: 'IF' } statement )?"
163
+
164
+ ptree = subject.parse(if_stmt)
165
+ expect(ptree.root).to be_kind_of(SequenceNode)
166
+ expect(ptree.root.subnodes[0]).to be_kind_of(SymbolNode)
167
+ expect(ptree.root.subnodes[0].name).to eq('IF')
168
+ expect(ptree.root.subnodes[1]).to be_kind_of(SymbolNode)
169
+ expect(ptree.root.subnodes[1].name).to eq('ifCondition')
170
+ expect(ptree.root.subnodes[2]).to be_kind_of(SymbolNode)
171
+ expect(ptree.root.subnodes[2].name).to eq('statement')
172
+ optional = ptree.root.subnodes[3]
173
+ expect(optional).to be_kind_of(SequenceNode)
174
+ expect(optional.repetition).to eq(:zero_or_one)
175
+ expect(optional.subnodes[0]).to be_kind_of(SymbolNode)
176
+ expect(optional.subnodes[0].name).to eq('ELSE')
177
+ expect(optional.subnodes[0].annotation).to eq({ 'match_closest' => 'IF' })
178
+ expect(optional.subnodes[1].name).to eq('statement')
179
+ end
180
+ end # context
181
+ end # describe
182
+ end # module
183
+ end # module