ruby-ll 1.1.3 → 2.0.0
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/README.md +68 -2
- data/doc/driver_architecture.md +32 -0
- data/ext/c/driver.c +71 -2
- data/ext/c/driver_config.c +1 -1
- data/ext/c/driver_config.h +1 -1
- data/ext/java/org/libll/Driver.java +63 -7
- data/lib/ll.rb +1 -0
- data/lib/ll/branch.rb +7 -1
- data/lib/ll/configuration_compiler.rb +34 -9
- data/lib/ll/driver.rb +4 -0
- data/lib/ll/grammar_compiler.rb +77 -27
- data/lib/ll/lexer.rb +75 -51
- data/lib/ll/operator.rb +26 -0
- data/lib/ll/parser.rb +129 -62
- data/lib/ll/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5d66bcacfb96b5c530ea468c1e6f9cc74a3d916
|
4
|
+
data.tar.gz: 4eba99c6eb0c02fd4945cc2767ec5487cd93b7d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 885e11cf3cfcb3f42644fbd4d0e79e34dbb5c9939e0916728517ba283a07b61b0f0dfaf6734285e112aa499aab4928a64b1fc14eecc2460139658e958542a6ee
|
7
|
+
data.tar.gz: 1f15f04b4abd4e573e12334e1db627ca899e24d91be250c048294e5503212a7eca375133723108732f07df7f7c8243f8beb665400cbe5a18669995fa1faf0841
|
data/README.md
CHANGED
@@ -278,8 +278,30 @@ return specific elements from it:
|
|
278
278
|
numbers = A B { val[0] };
|
279
279
|
|
280
280
|
Values returned by code blocks are passed to whatever other rule called it. This
|
281
|
-
allows code blocks to be used for building ASTs and the likes.
|
282
|
-
|
281
|
+
allows code blocks to be used for building ASTs and the likes.
|
282
|
+
|
283
|
+
If no explicit code block is defined then ruby-ll will generate one for you. If
|
284
|
+
a branch consists out of only a single step (e.g. `A = B;`) then only the first
|
285
|
+
value is returned, otherwise all values are returned.
|
286
|
+
|
287
|
+
This means that in the following example the output will be whatever value "C"
|
288
|
+
contains:
|
289
|
+
|
290
|
+
A = B { p val[0] };
|
291
|
+
B = C;
|
292
|
+
|
293
|
+
However, here the output would be `[C, D]` as the `B` rule's branch contains
|
294
|
+
multiple steps:
|
295
|
+
|
296
|
+
A = B { p val[0] };
|
297
|
+
B = C D;
|
298
|
+
|
299
|
+
To summarize (`# =>` denotes the return value):
|
300
|
+
|
301
|
+
A = B; # => B
|
302
|
+
A = B C; # => [B, C]
|
303
|
+
|
304
|
+
You can override this behaviour simply by defining your own code block.
|
283
305
|
|
284
306
|
ruby-ll parsers recurse into rules before unwinding, this means that the
|
285
307
|
inner-most rule is processed first.
|
@@ -301,6 +323,50 @@ name as a terminal, as such the following is invalid:
|
|
301
323
|
|
302
324
|
It's also an error to re-define an existing rule.
|
303
325
|
|
326
|
+
### Operators
|
327
|
+
|
328
|
+
Grammars can use two operators to define a sequence of terminals/non-terminals:
|
329
|
+
the star (`*`) and plus (`+`) operators.
|
330
|
+
|
331
|
+
The star operator indicates that something should occur 0 or more times. Here
|
332
|
+
the "B" identifier could occur 0 times, once, twice or many more times:
|
333
|
+
|
334
|
+
A = B*;
|
335
|
+
|
336
|
+
The plus operator indicates that something should occur at least once followed
|
337
|
+
by any number of more occurrences. For example, this grammar states that "B"
|
338
|
+
should occur at least once but can also occur, say, 10 times:
|
339
|
+
|
340
|
+
A = B+;
|
341
|
+
|
342
|
+
Operators can be applied either to a single terminal/rule or a series of
|
343
|
+
terminals/rules grouped together using parenthesis. For example, both are
|
344
|
+
perfectly valid:
|
345
|
+
|
346
|
+
A = B+;
|
347
|
+
A = (B C)+;
|
348
|
+
|
349
|
+
When calling an operator on a single terminal/rule the corresponding entry in
|
350
|
+
the `val` array is simply set to the terminal/rule value. For example:
|
351
|
+
|
352
|
+
A = B+ { p val[0] };
|
353
|
+
|
354
|
+
For input `B B B` this would output `[B, B, B]`.
|
355
|
+
|
356
|
+
However, when grouping multiple terminals/rules using parenthesis every
|
357
|
+
occurrence is wrapped in an Array. For example:
|
358
|
+
|
359
|
+
A = (B C)+ { p val[0] };
|
360
|
+
|
361
|
+
For input `B C B C` this would output `[[B, C], [B, C]]`. To work around this
|
362
|
+
you can simply move the group of identifiers to its own rule and only return
|
363
|
+
whatever you need:
|
364
|
+
|
365
|
+
A = A1+ { p val[0] };
|
366
|
+
A1 = B C { val[0] }; # only return "B"
|
367
|
+
|
368
|
+
For input `B C B C` this would output `[B, B]`.
|
369
|
+
|
304
370
|
## Conflicts
|
305
371
|
|
306
372
|
LL(1) grammars can have two kinds of conflicts in a rule:
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Driver Architecture
|
2
|
+
|
3
|
+
The actual parsing of input is handled by a so called "driver" represented as
|
4
|
+
the class `LL::Driver`. This class is written in either C or Java depending on
|
5
|
+
the Ruby platform that's being used. The rationale for this is simple:
|
6
|
+
performance. While Ruby is a great language it's sadly not fast enough to handle
|
7
|
+
parsing of large inputs in a way that doesn't either require lots of memory,
|
8
|
+
time or both.
|
9
|
+
|
10
|
+
Both the C and Java drivers try to use native data structures as much as
|
11
|
+
possible instead of using Ruby structures. For example, their internal parsing
|
12
|
+
stacks are native stacks. In case of Java this is an ArrayDeque, in case of C
|
13
|
+
this is a vector created using the [kvec][kvec] library as C doesn't have a
|
14
|
+
native vector structure.
|
15
|
+
|
16
|
+
The driver operates by iterating over every token supplied by the `each_token`
|
17
|
+
method (this method must be defined by a parser itself). For every input token a
|
18
|
+
callback function in C/Java is executed that determines what to parse and how to
|
19
|
+
parse it.
|
20
|
+
|
21
|
+
The parsing process largely operates on integers, only using Ruby objects where
|
22
|
+
absolutely required. For example, all steps of a rule's branch are represented
|
23
|
+
as integers. Lookup tables are also simply arrays of integers with terminals
|
24
|
+
being mapped directly to the indexes of these arrays. See ruby-ll's own parser
|
25
|
+
for examples. Note that the integers for the `rules` Array are in reverse order,
|
26
|
+
so everything that comes first is processed last.
|
27
|
+
|
28
|
+
For more information on the internals its best to refer to the C driver code
|
29
|
+
located in `ext/c/driver.c`. The Java code is largely based on this code safe
|
30
|
+
for some code comments here and there.
|
31
|
+
|
32
|
+
[kvec]: https://github.com/attractivechaos/klib/blob/master/kvec.h
|
data/ext/c/driver.c
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
#define T_TERMINAL 1
|
6
6
|
#define T_EPSILON 2
|
7
7
|
#define T_ACTION 3
|
8
|
+
#define T_STAR 4
|
9
|
+
#define T_PLUS 5
|
10
|
+
#define T_ADD_VALUE_STACK 6
|
11
|
+
#define T_APPEND_VALUE_STACK 7
|
8
12
|
|
9
13
|
ID id_config_const;
|
10
14
|
ID id_each_token;
|
@@ -66,6 +70,8 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
|
|
66
70
|
VALUE method;
|
67
71
|
VALUE action_args;
|
68
72
|
VALUE action_retval;
|
73
|
+
VALUE operator_buffer;
|
74
|
+
VALUE last_value;
|
69
75
|
long num_args;
|
70
76
|
long args_i;
|
71
77
|
|
@@ -113,8 +119,8 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
|
|
113
119
|
}
|
114
120
|
}
|
115
121
|
|
116
|
-
/*
|
117
|
-
if ( stack_type == T_RULE )
|
122
|
+
/* A rule or the "+" operator */
|
123
|
+
if ( stack_type == T_RULE || stack_type == T_PLUS )
|
118
124
|
{
|
119
125
|
production_i = state->config->table[stack_value][token_id];
|
120
126
|
|
@@ -132,6 +138,19 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
|
|
132
138
|
}
|
133
139
|
else
|
134
140
|
{
|
141
|
+
/*
|
142
|
+
Append a "*" operator for all following occurrences as they are
|
143
|
+
optional
|
144
|
+
*/
|
145
|
+
if ( stack_type == T_PLUS )
|
146
|
+
{
|
147
|
+
kv_push(long, state->stack, T_STAR);
|
148
|
+
kv_push(long, state->stack, stack_value);
|
149
|
+
|
150
|
+
kv_push(long, state->stack, T_APPEND_VALUE_STACK);
|
151
|
+
kv_push(long, state->stack, 0);
|
152
|
+
}
|
153
|
+
|
135
154
|
FOR(rule_i, state->config->rule_lengths[production_i])
|
136
155
|
{
|
137
156
|
kv_push(
|
@@ -142,6 +161,56 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
|
|
142
161
|
}
|
143
162
|
}
|
144
163
|
}
|
164
|
+
/* "*" operator */
|
165
|
+
else if ( stack_type == T_STAR )
|
166
|
+
{
|
167
|
+
production_i = state->config->table[stack_value][token_id];
|
168
|
+
|
169
|
+
if ( production_i != T_EOF )
|
170
|
+
{
|
171
|
+
kv_push(long, state->stack, T_STAR);
|
172
|
+
kv_push(long, state->stack, stack_value);
|
173
|
+
|
174
|
+
kv_push(long, state->stack, T_APPEND_VALUE_STACK);
|
175
|
+
kv_push(long, state->stack, 0);
|
176
|
+
|
177
|
+
FOR(rule_i, state->config->rule_lengths[production_i])
|
178
|
+
{
|
179
|
+
kv_push(
|
180
|
+
long,
|
181
|
+
state->stack,
|
182
|
+
state->config->rules[production_i][rule_i]
|
183
|
+
);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
/*
|
188
|
+
Adds a new array to the value stack that can be used to group operator
|
189
|
+
values together
|
190
|
+
*/
|
191
|
+
else if ( stack_type == T_ADD_VALUE_STACK )
|
192
|
+
{
|
193
|
+
operator_buffer = rb_ary_new();
|
194
|
+
|
195
|
+
kv_push(VALUE, state->value_stack, operator_buffer);
|
196
|
+
|
197
|
+
RB_GC_GUARD(operator_buffer);
|
198
|
+
}
|
199
|
+
/*
|
200
|
+
Appends the last value on the value stack to the operator buffer that
|
201
|
+
preceeds it.
|
202
|
+
*/
|
203
|
+
else if ( stack_type == T_APPEND_VALUE_STACK )
|
204
|
+
{
|
205
|
+
last_value = kv_pop(state->value_stack);
|
206
|
+
|
207
|
+
operator_buffer = kv_A(
|
208
|
+
state->value_stack,
|
209
|
+
kv_size(state->value_stack) - 1
|
210
|
+
);
|
211
|
+
|
212
|
+
rb_ary_push(operator_buffer, last_value);
|
213
|
+
}
|
145
214
|
/* Terminal */
|
146
215
|
else if ( stack_type == T_TERMINAL )
|
147
216
|
{
|
data/ext/c/driver_config.c
CHANGED
@@ -166,7 +166,7 @@ VALUE ll_driver_config_set_actions(VALUE self, VALUE array)
|
|
166
166
|
|
167
167
|
Data_Get_Struct(self, DriverConfig, config);
|
168
168
|
|
169
|
-
config->action_names = ALLOC_N(
|
169
|
+
config->action_names = ALLOC_N(VALUE, row_count);
|
170
170
|
config->action_arg_amounts = ALLOC_N(long, row_count);
|
171
171
|
|
172
172
|
FOR(rindex, row_count)
|
data/ext/c/driver_config.h
CHANGED
@@ -27,11 +27,15 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
27
27
|
@JRubyClass(name="LL::Driver", parent="Object")
|
28
28
|
public class Driver extends RubyObject
|
29
29
|
{
|
30
|
-
private static long T_EOF
|
31
|
-
private static long T_RULE
|
32
|
-
private static long T_TERMINAL
|
33
|
-
private static long T_EPSILON
|
34
|
-
private static long T_ACTION
|
30
|
+
private static long T_EOF = -1;
|
31
|
+
private static long T_RULE = 0;
|
32
|
+
private static long T_TERMINAL = 1;
|
33
|
+
private static long T_EPSILON = 2;
|
34
|
+
private static long T_ACTION = 3;
|
35
|
+
private static long T_STAR = 4;
|
36
|
+
private static long T_PLUS = 5;
|
37
|
+
private static long T_ADD_VALUE_STACK = 6;
|
38
|
+
private static long T_APPEND_VALUE_STACK = 7;
|
35
39
|
|
36
40
|
/**
|
37
41
|
* The current Ruby runtime.
|
@@ -132,8 +136,8 @@ public class Driver extends RubyObject
|
|
132
136
|
token_id = self.config.terminals.get(type);
|
133
137
|
}
|
134
138
|
|
135
|
-
//
|
136
|
-
if ( stack_type == self.T_RULE )
|
139
|
+
// A rule or the "+" operator
|
140
|
+
if ( stack_type == self.T_RULE || stack_type == self.T_PLUS )
|
137
141
|
{
|
138
142
|
Long production_i = self.config.table
|
139
143
|
.get(stack_value.intValue())
|
@@ -152,6 +156,17 @@ public class Driver extends RubyObject
|
|
152
156
|
}
|
153
157
|
else
|
154
158
|
{
|
159
|
+
// Append a "*" operator for all following
|
160
|
+
// occurrences as they are optional
|
161
|
+
if ( stack_type == self.T_PLUS )
|
162
|
+
{
|
163
|
+
stack.push(self.T_STAR);
|
164
|
+
stack.push(stack_value);
|
165
|
+
|
166
|
+
stack.push(self.T_APPEND_VALUE_STACK);
|
167
|
+
stack.push(Long.valueOf(0));
|
168
|
+
}
|
169
|
+
|
155
170
|
ArrayList<Long> row = self.config.rules
|
156
171
|
.get(production_i.intValue());
|
157
172
|
|
@@ -161,6 +176,47 @@ public class Driver extends RubyObject
|
|
161
176
|
}
|
162
177
|
}
|
163
178
|
}
|
179
|
+
// "*" operator
|
180
|
+
else if ( stack_type == self.T_STAR )
|
181
|
+
{
|
182
|
+
Long production_i = self.config.table
|
183
|
+
.get(stack_value.intValue())
|
184
|
+
.get(token_id.intValue());
|
185
|
+
|
186
|
+
if ( production_i != self.T_EOF )
|
187
|
+
{
|
188
|
+
stack.push(self.T_STAR);
|
189
|
+
stack.push(stack_value);
|
190
|
+
|
191
|
+
stack.push(self.T_APPEND_VALUE_STACK);
|
192
|
+
stack.push(Long.valueOf(0));
|
193
|
+
|
194
|
+
ArrayList<Long> row = self.config.rules
|
195
|
+
.get(production_i.intValue());
|
196
|
+
|
197
|
+
for ( int index = 0; index < row.size(); index++ )
|
198
|
+
{
|
199
|
+
stack.push(row.get(index));
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
// Adds a new array to the value stack that can be used to
|
204
|
+
// group operator values together
|
205
|
+
else if ( stack_type == self.T_ADD_VALUE_STACK )
|
206
|
+
{
|
207
|
+
RubyArray operator_buffer = self.runtime.newArray();
|
208
|
+
|
209
|
+
value_stack.push(operator_buffer);
|
210
|
+
}
|
211
|
+
// Appends the last value on the value stack to the operator
|
212
|
+
// buffer that preceeds it.
|
213
|
+
else if ( stack_type == self.T_APPEND_VALUE_STACK )
|
214
|
+
{
|
215
|
+
IRubyObject last_value = value_stack.pop();
|
216
|
+
RubyArray operator_buffer = (RubyArray) value_stack.peek();
|
217
|
+
|
218
|
+
operator_buffer.append(last_value);
|
219
|
+
}
|
164
220
|
// Terminal
|
165
221
|
else if ( stack_type == self.T_TERMINAL )
|
166
222
|
{
|
data/lib/ll.rb
CHANGED
@@ -18,6 +18,7 @@ require_relative 'll/rule'
|
|
18
18
|
require_relative 'll/branch'
|
19
19
|
require_relative 'll/terminal'
|
20
20
|
require_relative 'll/epsilon'
|
21
|
+
require_relative 'll/operator'
|
21
22
|
require_relative 'll/message'
|
22
23
|
require_relative 'll/ast/node'
|
23
24
|
require_relative 'll/erb_context'
|
data/lib/ll/branch.rb
CHANGED
@@ -8,11 +8,15 @@ module LL
|
|
8
8
|
# @return [Hash]
|
9
9
|
#
|
10
10
|
TYPES = {
|
11
|
-
:eof
|
12
|
-
:rule
|
13
|
-
:terminal
|
14
|
-
:epsilon
|
15
|
-
:action
|
11
|
+
:eof => -1,
|
12
|
+
:rule => 0,
|
13
|
+
:terminal => 1,
|
14
|
+
:epsilon => 2,
|
15
|
+
:action => 3,
|
16
|
+
:star => 4,
|
17
|
+
:plus => 5,
|
18
|
+
:add_value_stack => 6,
|
19
|
+
:append_value_stack => 7
|
16
20
|
}.freeze
|
17
21
|
|
18
22
|
##
|
@@ -105,7 +109,21 @@ module LL
|
|
105
109
|
|
106
110
|
grammar.rules.each do |rule|
|
107
111
|
rule.branches.each do |branch|
|
108
|
-
|
112
|
+
if branch.ruby_code
|
113
|
+
code = branch.ruby_code
|
114
|
+
|
115
|
+
# If a branch only contains a single, non-epsilon step we can just
|
116
|
+
# return that value as-is. This makes parsing code a little bit
|
117
|
+
# easier.
|
118
|
+
elsif !branch.ruby_code and branch.steps.length == 1 \
|
119
|
+
and !branch.steps[0].is_a?(Epsilon)
|
120
|
+
code = 'val[0]'
|
121
|
+
|
122
|
+
else
|
123
|
+
code = DEFAULT_RUBY_CODE
|
124
|
+
end
|
125
|
+
|
126
|
+
bodies[:"_rule_#{index}"] = code
|
109
127
|
|
110
128
|
index += 1
|
111
129
|
end
|
@@ -133,17 +151,24 @@ module LL
|
|
133
151
|
action_index += 1
|
134
152
|
|
135
153
|
branch.steps.reverse_each do |step|
|
136
|
-
if step.is_a?(
|
154
|
+
if step.is_a?(Terminal)
|
137
155
|
row << TYPES[:terminal]
|
138
156
|
row << term_indices[step] + 1
|
139
157
|
|
140
|
-
elsif step.is_a?(
|
158
|
+
elsif step.is_a?(Rule)
|
141
159
|
row << TYPES[:rule]
|
142
160
|
row << rule_indices[step]
|
143
161
|
|
144
|
-
elsif step.is_a?(
|
162
|
+
elsif step.is_a?(Epsilon)
|
145
163
|
row << TYPES[:epsilon]
|
146
164
|
row << 0
|
165
|
+
|
166
|
+
elsif step.is_a?(Operator)
|
167
|
+
row << TYPES[step.type]
|
168
|
+
row << rule_indices[step.receiver]
|
169
|
+
|
170
|
+
row << TYPES[:add_value_stack]
|
171
|
+
row << 0
|
147
172
|
end
|
148
173
|
end
|
149
174
|
|
data/lib/ll/driver.rb
CHANGED
@@ -30,6 +30,10 @@ module LL
|
|
30
30
|
message = "Unexpected #{token_type}, expected #{expected} instead"
|
31
31
|
when :eof
|
32
32
|
message = "Received #{token_type} but there's nothing left to parse"
|
33
|
+
when :star
|
34
|
+
message = %Q{Unexpected #{token_type} for a "*" operator}
|
35
|
+
when :plus
|
36
|
+
message = %Q{Unexpected #{token_type} for a "+" operator}
|
33
37
|
end
|
34
38
|
|
35
39
|
return message
|
data/lib/ll/grammar_compiler.rb
CHANGED
@@ -179,7 +179,7 @@ module LL
|
|
179
179
|
##
|
180
180
|
# Processes the assignment of terminals.
|
181
181
|
#
|
182
|
-
# @see #process
|
182
|
+
# @see [#process]
|
183
183
|
#
|
184
184
|
def on_terminals(node, compiled_grammar)
|
185
185
|
node.children.each do |child|
|
@@ -199,7 +199,7 @@ module LL
|
|
199
199
|
##
|
200
200
|
# Processes an %inner directive.
|
201
201
|
#
|
202
|
-
# @see #process
|
202
|
+
# @see [#process]
|
203
203
|
#
|
204
204
|
def on_inner(node, compiled_grammar)
|
205
205
|
compiled_grammar.inner = process(node.children[0], compiled_grammar)
|
@@ -208,7 +208,7 @@ module LL
|
|
208
208
|
##
|
209
209
|
# Processes a %header directive.
|
210
210
|
#
|
211
|
-
# @see #process
|
211
|
+
# @see [#process]
|
212
212
|
#
|
213
213
|
def on_header(node, compiled_grammar)
|
214
214
|
compiled_grammar.header = process(node.children[0], compiled_grammar)
|
@@ -217,7 +217,7 @@ module LL
|
|
217
217
|
##
|
218
218
|
# Processes a node containing Ruby source code.
|
219
219
|
#
|
220
|
-
# @see #process
|
220
|
+
# @see [#process]
|
221
221
|
# @return [String]
|
222
222
|
#
|
223
223
|
def on_ruby(node, compiled_grammar)
|
@@ -227,7 +227,7 @@ module LL
|
|
227
227
|
##
|
228
228
|
# Extracts the name from an identifier.
|
229
229
|
#
|
230
|
-
# @see #process
|
230
|
+
# @see [#process]
|
231
231
|
# @return [String]
|
232
232
|
#
|
233
233
|
def on_ident(node, compiled_grammar)
|
@@ -237,7 +237,7 @@ module LL
|
|
237
237
|
##
|
238
238
|
# Processes an epsilon.
|
239
239
|
#
|
240
|
-
# @see #process
|
240
|
+
# @see [#process]
|
241
241
|
# @return [LL::Epsilon]
|
242
242
|
#
|
243
243
|
def on_epsilon(node, compiled_grammar)
|
@@ -247,7 +247,7 @@ module LL
|
|
247
247
|
##
|
248
248
|
# Processes the assignment of a rule.
|
249
249
|
#
|
250
|
-
# @see #process
|
250
|
+
# @see [#process]
|
251
251
|
#
|
252
252
|
def on_rule(node, compiled_grammar)
|
253
253
|
name = process(node.children[0], compiled_grammar)
|
@@ -280,7 +280,7 @@ module LL
|
|
280
280
|
##
|
281
281
|
# Creates a basic prototype for a rule.
|
282
282
|
#
|
283
|
-
# @see #process
|
283
|
+
# @see [#process]
|
284
284
|
#
|
285
285
|
def on_rule_prototype(node, compiled_grammar)
|
286
286
|
name = process(node.children[0], compiled_grammar)
|
@@ -295,7 +295,7 @@ module LL
|
|
295
295
|
##
|
296
296
|
# Processes a single rule branch.
|
297
297
|
#
|
298
|
-
# @see #process
|
298
|
+
# @see [#process]
|
299
299
|
# @return [LL::Branch]
|
300
300
|
#
|
301
301
|
def on_branch(node, compiled_grammar)
|
@@ -313,33 +313,53 @@ module LL
|
|
313
313
|
##
|
314
314
|
# Processes the steps of a branch.
|
315
315
|
#
|
316
|
-
# @see #process
|
316
|
+
# @see [#process]
|
317
317
|
# @return [Array]
|
318
318
|
#
|
319
319
|
def on_steps(node, compiled_grammar)
|
320
|
-
|
320
|
+
return lookup_identifiers(node, compiled_grammar)
|
321
|
+
end
|
321
322
|
|
322
|
-
|
323
|
-
|
323
|
+
##
|
324
|
+
# Processes the "*" operator.
|
325
|
+
#
|
326
|
+
# @param [LL::AST::Node] node
|
327
|
+
# @param [LL::CompiledGrammar] compiled_grammar
|
328
|
+
# @return [LL::Operator]
|
329
|
+
#
|
330
|
+
def on_star(node, compiled_grammar)
|
331
|
+
steps = lookup_identifiers(node, compiled_grammar)
|
332
|
+
name = "_ll_star#{node.source_line.line}#{node.source_line.column}"
|
333
|
+
rule = Rule.new(name, node.source_line)
|
324
334
|
|
325
|
-
|
326
|
-
if retval.is_a?(String)
|
327
|
-
step = compiled_grammar.lookup_identifier(retval)
|
335
|
+
rule.add_branch(steps, node.source_line)
|
328
336
|
|
329
|
-
|
330
|
-
# Epsilon
|
331
|
-
else
|
332
|
-
step = retval
|
333
|
-
end
|
337
|
+
rule.increment_references
|
334
338
|
|
335
|
-
|
336
|
-
step.increment_references if step.respond_to?(:increment_references)
|
339
|
+
compiled_grammar.add_rule(rule)
|
337
340
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
+
return Operator.new(:star, rule, node.source_line)
|
342
|
+
end
|
343
|
+
|
344
|
+
##
|
345
|
+
# Processes the "+" operator.
|
346
|
+
#
|
347
|
+
# @param [LL::AST::Node] node
|
348
|
+
# @param [LL::CompiledGrammar] compiled_grammar
|
349
|
+
# @return [LL::Operator]
|
350
|
+
#
|
351
|
+
def on_plus(node, compiled_grammar)
|
352
|
+
steps = lookup_identifiers(node, compiled_grammar)
|
353
|
+
name = "_ll_plus#{node.source_line.line}#{node.source_line.column}"
|
354
|
+
rule = Rule.new(name, node.source_line)
|
355
|
+
|
356
|
+
rule.add_branch(steps, node.source_line)
|
341
357
|
|
342
|
-
|
358
|
+
rule.increment_references
|
359
|
+
|
360
|
+
compiled_grammar.add_rule(rule)
|
361
|
+
|
362
|
+
return Operator.new(:plus, rule, node.source_line)
|
343
363
|
end
|
344
364
|
|
345
365
|
private
|
@@ -355,5 +375,35 @@ module LL
|
|
355
375
|
node.source_line
|
356
376
|
)
|
357
377
|
end
|
378
|
+
|
379
|
+
##
|
380
|
+
# @see [#process]
|
381
|
+
# @return [Array]
|
382
|
+
#
|
383
|
+
def lookup_identifiers(node, compiled_grammar)
|
384
|
+
idents = []
|
385
|
+
|
386
|
+
node.children.each do |ident_node|
|
387
|
+
retval = process(ident_node, compiled_grammar)
|
388
|
+
|
389
|
+
# Literal rule/terminal names.
|
390
|
+
if retval.is_a?(String)
|
391
|
+
ident = compiled_grammar.lookup_identifier(retval)
|
392
|
+
|
393
|
+
undefined_identifier!(retval, ident_node, compiled_grammar) if !ident
|
394
|
+
# Epsilon
|
395
|
+
else
|
396
|
+
ident = retval
|
397
|
+
end
|
398
|
+
|
399
|
+
if ident
|
400
|
+
ident.increment_references if ident.respond_to?(:increment_references)
|
401
|
+
|
402
|
+
idents << ident
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
return idents
|
407
|
+
end
|
358
408
|
end # Compiler
|
359
409
|
end # LL
|
data/lib/ll/lexer.rb
CHANGED
@@ -64,49 +64,49 @@ self._ll_lexer_indicies = [
|
|
64
64
|
27, 1, 1, 1, 1, 1, 1, 1,
|
65
65
|
1, 1, 1, 1, 1, 1, 1, 1,
|
66
66
|
1, 1, 1, 1, 1, 1, 26, 1,
|
67
|
-
1, 28, 1, 29, 1, 1,
|
68
|
-
|
67
|
+
1, 28, 1, 29, 1, 1, 30, 31,
|
68
|
+
32, 33, 1, 1, 1, 1, 25, 25,
|
69
69
|
25, 25, 25, 25, 25, 25, 25, 25,
|
70
|
-
|
70
|
+
34, 35, 1, 36, 1, 1, 1, 25,
|
71
71
|
25, 25, 25, 25, 25, 25, 25, 25,
|
72
72
|
25, 25, 25, 25, 25, 25, 25, 25,
|
73
73
|
25, 25, 25, 25, 25, 25, 25, 25,
|
74
|
-
25, 1, 1, 1, 1,
|
74
|
+
25, 1, 1, 1, 1, 37, 1, 25,
|
75
75
|
25, 25, 25, 25, 25, 25, 25, 25,
|
76
76
|
25, 25, 25, 25, 25, 25, 25, 25,
|
77
77
|
25, 25, 25, 25, 25, 25, 25, 25,
|
78
|
-
25,
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
78
|
+
25, 38, 39, 1, 1, 1, 25, 40,
|
79
|
+
40, 40, 40, 40, 40, 40, 40, 40,
|
80
|
+
40, 40, 40, 40, 40, 40, 40, 40,
|
81
|
+
40, 40, 40, 40, 40, 40, 40, 40,
|
82
|
+
40, 40, 40, 40, 40, 40, 40, 40,
|
83
|
+
40, 40, 40, 40, 40, 40, 40, 40,
|
84
|
+
40, 40, 40, 40, 40, 40, 40, 25,
|
85
85
|
25, 25, 25, 25, 25, 25, 25, 25,
|
86
|
-
25,
|
86
|
+
25, 40, 40, 40, 40, 40, 40, 40,
|
87
87
|
25, 25, 25, 25, 25, 25, 25, 25,
|
88
88
|
25, 25, 25, 25, 25, 25, 25, 25,
|
89
89
|
25, 25, 25, 25, 25, 25, 25, 25,
|
90
|
-
25, 25,
|
90
|
+
25, 25, 40, 40, 40, 40, 25, 40,
|
91
91
|
25, 25, 25, 25, 25, 25, 25, 25,
|
92
92
|
25, 25, 25, 25, 25, 25, 25, 25,
|
93
93
|
25, 25, 25, 25, 25, 25, 25, 25,
|
94
|
-
25, 25,
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
94
|
+
25, 25, 40, 40, 40, 40, 40, 25,
|
95
|
+
41, 28, 43, 42, 42, 42, 42, 42,
|
96
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
97
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
98
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
99
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
100
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
101
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
102
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
103
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
104
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
105
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
106
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
107
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
108
|
+
42, 42, 42, 42, 42, 42, 42, 42,
|
109
|
+
42, 42, 42, 44, 42, 45, 42, 0
|
110
110
|
]
|
111
111
|
|
112
112
|
class << self
|
@@ -118,8 +118,8 @@ self._ll_lexer_trans_targs = [
|
|
118
118
|
6, 22, 8, 9, 10, 22, 12, 13,
|
119
119
|
22, 15, 16, 17, 18, 19, 20, 21,
|
120
120
|
22, 23, 22, 22, 24, 1, 22, 22,
|
121
|
-
22,
|
122
|
-
25, 25
|
121
|
+
22, 22, 22, 22, 22, 23, 22, 22,
|
122
|
+
22, 22, 25, 25, 25, 25
|
123
123
|
]
|
124
124
|
|
125
125
|
class << self
|
@@ -132,7 +132,7 @@ self._ll_lexer_trans_actions = [
|
|
132
132
|
3, 0, 0, 0, 0, 0, 0, 0,
|
133
133
|
4, 7, 8, 9, 0, 0, 10, 11,
|
134
134
|
12, 13, 14, 15, 16, 17, 18, 19,
|
135
|
-
20, 21
|
135
|
+
20, 21, 22, 23, 24, 25
|
136
136
|
]
|
137
137
|
|
138
138
|
class << self
|
@@ -164,8 +164,8 @@ end
|
|
164
164
|
self._ll_lexer_eof_trans = [
|
165
165
|
0, 0, 0, 0, 0, 0, 0, 0,
|
166
166
|
0, 0, 0, 0, 0, 0, 0, 0,
|
167
|
-
0, 0, 0, 0, 0, 0, 0,
|
168
|
-
|
167
|
+
0, 0, 0, 0, 0, 0, 0, 41,
|
168
|
+
42, 0
|
169
169
|
]
|
170
170
|
|
171
171
|
class << self
|
@@ -312,13 +312,13 @@ ts = p
|
|
312
312
|
cs = _ll_lexer_trans_targs[_trans]
|
313
313
|
if _ll_lexer_trans_actions[_trans] != 0
|
314
314
|
case _ll_lexer_trans_actions[_trans]
|
315
|
-
when
|
315
|
+
when 24 then
|
316
316
|
# line 188 "lib/ll/lexer.rl"
|
317
317
|
begin
|
318
318
|
te = p+1
|
319
319
|
begin brace_count += 1 end
|
320
320
|
end
|
321
|
-
when
|
321
|
+
when 25 then
|
322
322
|
# line 190 "lib/ll/lexer.rl"
|
323
323
|
begin
|
324
324
|
te = p+1
|
@@ -338,7 +338,7 @@ te = p+1
|
|
338
338
|
end
|
339
339
|
end
|
340
340
|
end
|
341
|
-
when
|
341
|
+
when 22 then
|
342
342
|
# line 206 "lib/ll/lexer.rl"
|
343
343
|
begin
|
344
344
|
te = p+1
|
@@ -367,33 +367,57 @@ te = p+1
|
|
367
367
|
te = p+1
|
368
368
|
begin emit(:T_HEADER, ts, te) end
|
369
369
|
end
|
370
|
-
when
|
370
|
+
when 16 then
|
371
371
|
# line 220 "lib/ll/lexer.rl"
|
372
372
|
begin
|
373
373
|
te = p+1
|
374
374
|
begin emit(:T_EQUALS, ts, te) end
|
375
375
|
end
|
376
|
-
when
|
376
|
+
when 14 then
|
377
377
|
# line 221 "lib/ll/lexer.rl"
|
378
378
|
begin
|
379
379
|
te = p+1
|
380
380
|
begin emit(:T_COLON, ts, te) end
|
381
381
|
end
|
382
|
-
when
|
382
|
+
when 15 then
|
383
383
|
# line 222 "lib/ll/lexer.rl"
|
384
384
|
begin
|
385
385
|
te = p+1
|
386
386
|
begin emit(:T_SEMICOLON, ts, te) end
|
387
387
|
end
|
388
|
-
when
|
388
|
+
when 19 then
|
389
389
|
# line 223 "lib/ll/lexer.rl"
|
390
390
|
begin
|
391
391
|
te = p+1
|
392
392
|
begin emit(:T_PIPE, ts, te) end
|
393
393
|
end
|
394
|
-
when
|
394
|
+
when 13 then
|
395
|
+
# line 225 "lib/ll/lexer.rl"
|
396
|
+
begin
|
397
|
+
te = p+1
|
398
|
+
begin emit(:T_PLUS, ts, te) end
|
399
|
+
end
|
400
|
+
when 12 then
|
395
401
|
# line 226 "lib/ll/lexer.rl"
|
396
402
|
begin
|
403
|
+
te = p+1
|
404
|
+
begin emit(:T_STAR, ts, te) end
|
405
|
+
end
|
406
|
+
when 10 then
|
407
|
+
# line 227 "lib/ll/lexer.rl"
|
408
|
+
begin
|
409
|
+
te = p+1
|
410
|
+
begin emit(:T_LPAREN, ts, te) end
|
411
|
+
end
|
412
|
+
when 11 then
|
413
|
+
# line 228 "lib/ll/lexer.rl"
|
414
|
+
begin
|
415
|
+
te = p+1
|
416
|
+
begin emit(:T_RPAREN, ts, te) end
|
417
|
+
end
|
418
|
+
when 18 then
|
419
|
+
# line 230 "lib/ll/lexer.rl"
|
420
|
+
begin
|
397
421
|
te = p+1
|
398
422
|
begin
|
399
423
|
mark = ts + 1
|
@@ -405,26 +429,26 @@ te = p+1
|
|
405
429
|
cs = 25;
|
406
430
|
end
|
407
431
|
end
|
408
|
-
when
|
432
|
+
when 21 then
|
409
433
|
# line 213 "lib/ll/lexer.rl"
|
410
434
|
begin
|
411
435
|
te = p
|
412
436
|
p = p - 1; end
|
413
|
-
when
|
437
|
+
when 20 then
|
414
438
|
# line 1 "NONE"
|
415
439
|
begin
|
416
440
|
case act
|
417
441
|
when 16 then
|
418
442
|
begin begin p = ((te))-1; end
|
419
443
|
emit(:T_EPSILON, ts, te) end
|
420
|
-
when
|
444
|
+
when 22 then
|
421
445
|
begin begin p = ((te))-1; end
|
422
446
|
|
423
447
|
emit(:T_IDENT, ts, te)
|
424
448
|
end
|
425
449
|
end
|
426
450
|
end
|
427
|
-
when
|
451
|
+
when 23 then
|
428
452
|
# line 148 "lib/ll/lexer.rl"
|
429
453
|
begin
|
430
454
|
|
@@ -458,7 +482,7 @@ te = p+1
|
|
458
482
|
begin
|
459
483
|
te = p+1
|
460
484
|
end
|
461
|
-
when
|
485
|
+
when 17 then
|
462
486
|
# line 1 "NONE"
|
463
487
|
begin
|
464
488
|
te = p+1
|
@@ -473,8 +497,8 @@ te = p+1
|
|
473
497
|
end
|
474
498
|
# line 168 "lib/ll/lexer.rl"
|
475
499
|
begin
|
476
|
-
act =
|
477
|
-
# line
|
500
|
+
act = 22; end
|
501
|
+
# line 501 "lib/ll/lexer.rb"
|
478
502
|
end
|
479
503
|
end
|
480
504
|
end
|
@@ -484,7 +508,7 @@ act = 18; end
|
|
484
508
|
# line 1 "NONE"
|
485
509
|
begin
|
486
510
|
ts = nil; end
|
487
|
-
# line
|
511
|
+
# line 511 "lib/ll/lexer.rb"
|
488
512
|
end
|
489
513
|
|
490
514
|
if cs == 0
|
@@ -576,7 +600,7 @@ end
|
|
576
600
|
end
|
577
601
|
|
578
602
|
|
579
|
-
# line
|
603
|
+
# line 242 "lib/ll/lexer.rl"
|
580
604
|
|
581
605
|
end # Lexer
|
582
606
|
end # Oga
|
data/lib/ll/operator.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module LL
|
2
|
+
##
|
3
|
+
# Class for operators such as + and *.
|
4
|
+
#
|
5
|
+
class Operator
|
6
|
+
attr_reader :type, :receiver, :source_line
|
7
|
+
|
8
|
+
##
|
9
|
+
# @param [Symbol] type
|
10
|
+
# @param [LL::Rule] receiver
|
11
|
+
# @param [LL::SourceLine] source_line
|
12
|
+
#
|
13
|
+
def initialize(type, receiver, source_line)
|
14
|
+
@type = type
|
15
|
+
@receiver = receiver
|
16
|
+
@source_line = source_line
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# @return [String]
|
21
|
+
#
|
22
|
+
def inspect
|
23
|
+
return "Operator(type: #{type.inspect}, receiver: #{receiver.inspect})"
|
24
|
+
end
|
25
|
+
end # Operator
|
26
|
+
end # LL
|
data/lib/ll/parser.rb
CHANGED
@@ -19,6 +19,10 @@ class Parser < LL::Driver
|
|
19
19
|
:T_PIPE, # 9
|
20
20
|
:T_EPSILON, # 10
|
21
21
|
:T_SEMICOLON, # 11
|
22
|
+
:T_STAR, # 12
|
23
|
+
:T_PLUS, # 13
|
24
|
+
:T_LPAREN, # 14
|
25
|
+
:T_RPAREN, # 15
|
22
26
|
].freeze
|
23
27
|
|
24
28
|
CONFIG.rules = [
|
@@ -26,7 +30,7 @@ class Parser < LL::Driver
|
|
26
30
|
[3, 1, 2, 0], # 1
|
27
31
|
[3, 2, 0, 1, 0, 2], # 2
|
28
32
|
[3, 3, 2, 0], # 3
|
29
|
-
[3, 4, 0,
|
33
|
+
[3, 4, 0, 23], # 4
|
30
34
|
[3, 5, 0, 3], # 5
|
31
35
|
[3, 6, 0, 5], # 6
|
32
36
|
[3, 7, 0, 6], # 7
|
@@ -35,45 +39,59 @@ class Parser < LL::Driver
|
|
35
39
|
[3, 10, 0, 4, 0, 10, 1, 8, 1, 8], # 10
|
36
40
|
[3, 11, 2, 0], # 11
|
37
41
|
[3, 12, 1, 11, 0, 8, 1, 3], # 12
|
38
|
-
[3, 13, 0,
|
39
|
-
[3, 14, 0,
|
42
|
+
[3, 13, 0, 20, 1, 4], # 13
|
43
|
+
[3, 14, 0, 20, 1, 5], # 14
|
40
44
|
[3, 15, 0, 9, 0, 10], # 15
|
41
45
|
[3, 16, 0, 8], # 16
|
42
46
|
[3, 17, 2, 0], # 17
|
43
47
|
[3, 18, 1, 6], # 18
|
44
|
-
[3, 19, 0,
|
45
|
-
[3, 20, 0,
|
46
|
-
[3, 21,
|
47
|
-
[3, 22,
|
48
|
-
[3, 23, 0,
|
49
|
-
[3, 24,
|
50
|
-
[3, 25,
|
51
|
-
[3, 26,
|
52
|
-
[3, 27,
|
53
|
-
[3, 28,
|
54
|
-
[3, 29,
|
48
|
+
[3, 19, 0, 12, 0, 13], # 19
|
49
|
+
[3, 20, 0, 15, 1, 15, 0, 8, 1, 14], # 20
|
50
|
+
[3, 21, 0, 11], # 21
|
51
|
+
[3, 22, 2, 0], # 22
|
52
|
+
[3, 23, 0, 14, 0, 10], # 23
|
53
|
+
[3, 24, 0, 15], # 24
|
54
|
+
[3, 25, 2, 0], # 25
|
55
|
+
[3, 26, 1, 13], # 26
|
56
|
+
[3, 27, 1, 12], # 27
|
57
|
+
[3, 28, 0, 11], # 28
|
58
|
+
[3, 29, 0, 17], # 29
|
59
|
+
[3, 30, 1, 10], # 30
|
60
|
+
[3, 31, 0, 19, 0, 16], # 31
|
61
|
+
[3, 32, 0, 20], # 32
|
62
|
+
[3, 33, 2, 0], # 33
|
63
|
+
[3, 34, 1, 1], # 34
|
64
|
+
[3, 35, 0, 22, 0, 18], # 35
|
65
|
+
[3, 36, 0, 21, 1, 9], # 36
|
66
|
+
[3, 37, 2, 0], # 37
|
67
|
+
[3, 38, 1, 11, 0, 21, 1, 7, 0, 10], # 38
|
55
68
|
].freeze
|
56
69
|
|
57
70
|
CONFIG.table = [
|
58
|
-
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 0
|
59
|
-
[3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3], # 1
|
60
|
-
[-1, -1, 5, 6, 7, 8, 4, -1, -1, -1, -1, -1], # 2
|
61
|
-
[-1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 3
|
62
|
-
[11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 11], # 4
|
63
|
-
[-1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1], # 5
|
64
|
-
[-1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1], # 6
|
65
|
-
[-1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1], # 7
|
66
|
-
[-1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1], # 8
|
67
|
-
[17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17], # 9
|
68
|
-
[-1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1], # 10
|
69
|
-
[-1, -1, -1, -1, -1, -1, 19, -1, -1, -1, 20, -1], # 11
|
70
|
-
[
|
71
|
-
[-1, -1, -1, -1, -1, -1,
|
72
|
-
[
|
73
|
-
[-1,
|
74
|
-
[-1, -1, -1, -1, -1, -1,
|
75
|
-
[
|
76
|
-
[-1, -1, -1, -1, -1, -1,
|
71
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 0
|
72
|
+
[3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3], # 1
|
73
|
+
[-1, -1, 5, 6, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 2
|
74
|
+
[-1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 3
|
75
|
+
[11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 11, 11, 11, 11, 11], # 4
|
76
|
+
[-1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 5
|
77
|
+
[-1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 6
|
78
|
+
[-1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 7
|
79
|
+
[-1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 8
|
80
|
+
[17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17], # 9
|
81
|
+
[-1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 10
|
82
|
+
[-1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, 20, -1], # 11
|
83
|
+
[22, 22, 22, 22, 22, 22, 21, 22, 22, 22, 22, 22, 22, 22, 21, 22], # 12
|
84
|
+
[-1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 13
|
85
|
+
[25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 25, 25], # 14
|
86
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, 26, -1, -1], # 15
|
87
|
+
[-1, -1, -1, -1, -1, -1, 28, -1, -1, -1, 29, -1, -1, -1, 28, -1], # 16
|
88
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1], # 17
|
89
|
+
[-1, -1, -1, -1, -1, -1, 31, -1, -1, -1, 31, -1, -1, -1, 31, -1], # 18
|
90
|
+
[33, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33], # 19
|
91
|
+
[-1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 20
|
92
|
+
[-1, -1, -1, -1, -1, -1, 35, -1, -1, -1, 35, -1, -1, -1, 35, -1], # 21
|
93
|
+
[37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37], # 22
|
94
|
+
[-1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 23
|
77
95
|
].freeze
|
78
96
|
|
79
97
|
CONFIG.actions = [
|
@@ -96,17 +114,26 @@ class Parser < LL::Driver
|
|
96
114
|
[:_rule_16, 1], # 16
|
97
115
|
[:_rule_17, 0], # 17
|
98
116
|
[:_rule_18, 1], # 18
|
99
|
-
[:_rule_19,
|
100
|
-
[:_rule_20,
|
117
|
+
[:_rule_19, 2], # 19
|
118
|
+
[:_rule_20, 4], # 20
|
101
119
|
[:_rule_21, 1], # 21
|
102
|
-
[:_rule_22,
|
103
|
-
[:_rule_23,
|
104
|
-
[:_rule_24,
|
105
|
-
[:_rule_25,
|
106
|
-
[:_rule_26,
|
107
|
-
[:_rule_27,
|
108
|
-
[:_rule_28,
|
109
|
-
[:_rule_29,
|
120
|
+
[:_rule_22, 0], # 22
|
121
|
+
[:_rule_23, 2], # 23
|
122
|
+
[:_rule_24, 1], # 24
|
123
|
+
[:_rule_25, 0], # 25
|
124
|
+
[:_rule_26, 1], # 26
|
125
|
+
[:_rule_27, 1], # 27
|
126
|
+
[:_rule_28, 1], # 28
|
127
|
+
[:_rule_29, 1], # 29
|
128
|
+
[:_rule_30, 1], # 30
|
129
|
+
[:_rule_31, 2], # 31
|
130
|
+
[:_rule_32, 1], # 32
|
131
|
+
[:_rule_33, 0], # 33
|
132
|
+
[:_rule_34, 1], # 34
|
133
|
+
[:_rule_35, 2], # 35
|
134
|
+
[:_rule_36, 2], # 36
|
135
|
+
[:_rule_37, 0], # 37
|
136
|
+
[:_rule_38, 4], # 38
|
110
137
|
].freeze
|
111
138
|
|
112
139
|
##
|
@@ -158,7 +185,7 @@ class Parser < LL::Driver
|
|
158
185
|
end
|
159
186
|
|
160
187
|
def _rule_2(val)
|
161
|
-
val[0]
|
188
|
+
[val[0], *val[1]]
|
162
189
|
end
|
163
190
|
|
164
191
|
def _rule_3(val)
|
@@ -166,23 +193,23 @@ class Parser < LL::Driver
|
|
166
193
|
end
|
167
194
|
|
168
195
|
def _rule_4(val)
|
169
|
-
val
|
196
|
+
val[0]
|
170
197
|
end
|
171
198
|
|
172
199
|
def _rule_5(val)
|
173
|
-
val
|
200
|
+
val[0]
|
174
201
|
end
|
175
202
|
|
176
203
|
def _rule_6(val)
|
177
|
-
val
|
204
|
+
val[0]
|
178
205
|
end
|
179
206
|
|
180
207
|
def _rule_7(val)
|
181
|
-
val
|
208
|
+
val[0]
|
182
209
|
end
|
183
210
|
|
184
211
|
def _rule_8(val)
|
185
|
-
val
|
212
|
+
val[0]
|
186
213
|
end
|
187
214
|
|
188
215
|
def _rule_9(val)
|
@@ -192,7 +219,7 @@ class Parser < LL::Driver
|
|
192
219
|
end
|
193
220
|
|
194
221
|
def _rule_10(val)
|
195
|
-
[val[2]
|
222
|
+
[val[2], *val[3]]
|
196
223
|
end
|
197
224
|
|
198
225
|
def _rule_11(val)
|
@@ -218,7 +245,7 @@ class Parser < LL::Driver
|
|
218
245
|
end
|
219
246
|
|
220
247
|
def _rule_15(val)
|
221
|
-
[val[0]
|
248
|
+
[val[0], *val[1]]
|
222
249
|
end
|
223
250
|
|
224
251
|
def _rule_16(val)
|
@@ -236,22 +263,62 @@ class Parser < LL::Driver
|
|
236
263
|
end
|
237
264
|
|
238
265
|
def _rule_19(val)
|
266
|
+
[val[0], *val[1]]
|
267
|
+
end
|
268
|
+
|
269
|
+
def _rule_20(val)
|
270
|
+
|
271
|
+
[s(val[3][0], val[1], :source_line => val[0].source_line)]
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
def _rule_21(val)
|
276
|
+
val[0]
|
277
|
+
end
|
278
|
+
|
279
|
+
def _rule_22(val)
|
280
|
+
val
|
281
|
+
end
|
282
|
+
|
283
|
+
def _rule_23(val)
|
284
|
+
|
285
|
+
val[1] ? s(val[1][0], [val[0]], :source_line => val[1][1]) : val[0]
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
def _rule_24(val)
|
290
|
+
val[0]
|
291
|
+
end
|
292
|
+
|
293
|
+
def _rule_25(val)
|
294
|
+
nil
|
295
|
+
end
|
296
|
+
|
297
|
+
def _rule_26(val)
|
298
|
+
[:plus, val[0].source_line]
|
299
|
+
end
|
300
|
+
|
301
|
+
def _rule_27(val)
|
302
|
+
[:star, val[0].source_line]
|
303
|
+
end
|
304
|
+
|
305
|
+
def _rule_28(val)
|
239
306
|
|
240
307
|
s(:steps, val[0], :source_line => val[0][0].source_line)
|
241
308
|
|
242
309
|
end
|
243
310
|
|
244
|
-
def
|
311
|
+
def _rule_29(val)
|
245
312
|
|
246
313
|
s(:steps, [val[0]], :source_line => val[0].source_line)
|
247
314
|
|
248
315
|
end
|
249
316
|
|
250
|
-
def
|
317
|
+
def _rule_30(val)
|
251
318
|
s(:epsilon, [], :source_line => val[0].source_line)
|
252
319
|
end
|
253
320
|
|
254
|
-
def
|
321
|
+
def _rule_31(val)
|
255
322
|
|
256
323
|
steps = [val[0]]
|
257
324
|
|
@@ -261,31 +328,31 @@ class Parser < LL::Driver
|
|
261
328
|
|
262
329
|
end
|
263
330
|
|
264
|
-
def
|
331
|
+
def _rule_32(val)
|
265
332
|
val[0]
|
266
333
|
end
|
267
334
|
|
268
|
-
def
|
335
|
+
def _rule_33(val)
|
269
336
|
nil
|
270
337
|
end
|
271
338
|
|
272
|
-
def
|
339
|
+
def _rule_34(val)
|
273
340
|
s(:ruby, [val[0].value], :source_line => val[0].source_line)
|
274
341
|
end
|
275
342
|
|
276
|
-
def
|
277
|
-
[val[0]
|
343
|
+
def _rule_35(val)
|
344
|
+
[val[0], *val[1]]
|
278
345
|
end
|
279
346
|
|
280
|
-
def
|
347
|
+
def _rule_36(val)
|
281
348
|
val[1]
|
282
349
|
end
|
283
350
|
|
284
|
-
def
|
351
|
+
def _rule_37(val)
|
285
352
|
val
|
286
353
|
end
|
287
354
|
|
288
|
-
def
|
355
|
+
def _rule_38(val)
|
289
356
|
|
290
357
|
s(:rule, [val[0], *val[2]], :source_line => val[0].source_line)
|
291
358
|
|
data/lib/ll/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-ll
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yorick Peterse
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ast
|
@@ -150,6 +150,7 @@ files:
|
|
150
150
|
- bin/ruby-ll
|
151
151
|
- doc/DCO.md
|
152
152
|
- doc/css/common.css
|
153
|
+
- doc/driver_architecture.md
|
153
154
|
- ext/c/driver.c
|
154
155
|
- ext/c/driver.h
|
155
156
|
- ext/c/driver_config.c
|
@@ -180,6 +181,7 @@ files:
|
|
180
181
|
- lib/ll/grammar_compiler.rb
|
181
182
|
- lib/ll/lexer.rb
|
182
183
|
- lib/ll/message.rb
|
184
|
+
- lib/ll/operator.rb
|
183
185
|
- lib/ll/parser.rb
|
184
186
|
- lib/ll/parser_error.rb
|
185
187
|
- lib/ll/rule.rb
|