ruby-ll 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef87cedfa33d3340b77133abff1bdb11f5ad767e
4
- data.tar.gz: 6e25ecbd4a78bc7f3469bba05d85a1cd9634b13a
3
+ metadata.gz: 6c4816c655c4f583b8ccbe2323616f6f39cf4df3
4
+ data.tar.gz: bae34b457281dba52a2164adbd39db03a4a37031
5
5
  SHA512:
6
- metadata.gz: 07561fc9d28c285ec101c5f9d2c67f16f15b700efd814af5a49174e9e47de90f44f2ffb0859d039f7022bd494f74b8867677c5fd93b6189dd44c40367e5dc62d
7
- data.tar.gz: 35a3352d8d2207937d5e1d8657f2c366f8417e6604fc2aef88effe9ed6d94a710e01b8ce4830881ca439fb7fa25a4b326e49a5157a925277d6cc260e4ae5c3f1
6
+ metadata.gz: c656e1ebf77d46bbeb574fa21b291d765694e16b41648cf7b78f2eb35015b8174a4f83ccef9f577893214b9d1322845913bb72f397271b0a188bba3b83bb38d0
7
+ data.tar.gz: 04acbb673f7a50f50832e16bf4ae7abbcad4b4311ef3843484afe75da76511ce749d0e7f432411b331192a6f04d437db5bbf90e30a71e6928a84ce8423f4acdc
data/README.md CHANGED
@@ -44,6 +44,12 @@ When hacking on Oga you'll also need to have the following installed:
44
44
  * Ragel 6 for building the grammar lexer
45
45
  * javac for building the JRuby extension
46
46
 
47
+ ## Installation
48
+
49
+ ruby-ll can be installed from RubyGems:
50
+
51
+ gem install ruby-ll
52
+
47
53
  ## Usage
48
54
 
49
55
  The CLI takes a grammar input file (see below for the exact syntax) with the
@@ -74,6 +80,13 @@ parsing simply call the `parse` method:
74
80
  The return value of this method is whatever the root rule (= the first rule
75
81
  defined) returned.
76
82
 
83
+ ## Error Handling
84
+
85
+ Parser errors are handled by `LL::Driver#parser_error`. By default this method
86
+ raises an instance of `LL::ParserError` with a message depending on the current
87
+ parser context and input. If you want to customize this behaviour simply
88
+ overwrite the method (e.g. in an `%inner` block).
89
+
77
90
  ## Grammar Syntax
78
91
 
79
92
  The syntax of a ruby-ll grammar file is fairly simple and consists out of
@@ -353,7 +366,7 @@ performance gains of ruby-ll over Racc are as following:
353
366
  | JRuby 9000 pre1 | 7.50x |
354
367
 
355
368
  This benchmark was run on a Thinkpad T520 laptop so it's probably best to run
356
- the bencharmk yourself to see how it behaves on your platform.
369
+ the benchmark yourself to see how it behaves on your platform.
357
370
 
358
371
  Depending on the complexity of your parser you might end up with different
359
372
  different numbers. The above metrics are simply an indication of the maximum
data/doc/changelog.md CHANGED
@@ -3,6 +3,17 @@
3
3
  This document contains details of the various releases and their release dates.
4
4
  Dates are in the format `yyyy-mm-dd`.
5
5
 
6
+ ## 1.1.0 - 2015-02-16
7
+
8
+ This release changes the way error handling is done. Instead of having multiple,
9
+ separate error callbacks there's now only one error callback:
10
+ `LL::Driver#parser_error`. See commit 22b6081e37509d10e3b31d6593b0a7f2e5fd7839
11
+ for more information.
12
+
13
+ While this change technically breaks backwards compatibility I do not consider
14
+ the old error handling system part of the public API, mainly due to it being
15
+ extremely painful to use.
16
+
6
17
  ## 1.0.0 - 2015-02-13
7
18
 
8
19
  The first public release of ruby-ll!
data/ext/c/driver.c CHANGED
@@ -9,10 +9,7 @@
9
9
  ID id_config_const;
10
10
  ID id_each_token;
11
11
  ID id_send;
12
-
13
- ID id_stack_input_error;
14
- ID id_unexpected_input_error;
15
- ID id_invalid_terminal_error;
12
+ ID id_parser_error;
16
13
 
17
14
  /**
18
15
  * Releases the memory of the driver's internal state and associated objects.
@@ -91,7 +88,15 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
91
88
  {
92
89
  if ( kv_size(state->stack) == 0 )
93
90
  {
94
- rb_funcall(self, id_unexpected_input_error, 1, token);
91
+ rb_funcall(
92
+ self,
93
+ id_parser_error,
94
+ 4,
95
+ INT2NUM(-1),
96
+ INT2NUM(-1),
97
+ type,
98
+ value
99
+ );
95
100
  }
96
101
 
97
102
  stack_value = kv_pop(state->stack);
@@ -117,10 +122,12 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
117
122
  {
118
123
  rb_funcall(
119
124
  self,
120
- id_stack_input_error,
121
- 2,
125
+ id_parser_error,
126
+ 4,
127
+ INT2NUM(stack_type),
122
128
  INT2NUM(stack_value),
123
- token
129
+ type,
130
+ value
124
131
  );
125
132
  }
126
133
  else
@@ -150,10 +157,12 @@ VALUE ll_driver_each_token(VALUE token, VALUE self)
150
157
  {
151
158
  rb_funcall(
152
159
  self,
153
- id_invalid_terminal_error,
154
- 2,
155
- INT2NUM(token_id),
156
- INT2NUM(stack_value)
160
+ id_parser_error,
161
+ 4,
162
+ INT2NUM(stack_type),
163
+ INT2NUM(stack_value),
164
+ type,
165
+ value
157
166
  );
158
167
  }
159
168
  }
@@ -249,10 +258,8 @@ void Init_ll_driver()
249
258
 
250
259
  rb_define_alloc_func(cDriver, ll_driver_allocate);
251
260
 
252
- id_send = rb_intern("send");
253
- id_config_const = rb_intern("CONFIG");
254
- id_each_token = rb_intern("each_token");
255
- id_stack_input_error = rb_intern("stack_input_error");
256
- id_invalid_terminal_error = rb_intern("invalid_terminal_error");
257
- id_unexpected_input_error = rb_intern("unexpected_input_error");
261
+ id_send = rb_intern("send");
262
+ id_config_const = rb_intern("CONFIG");
263
+ id_each_token = rb_intern("each_token");
264
+ id_parser_error = rb_intern("parser_error");
258
265
  }
@@ -113,11 +113,14 @@ public class Driver extends RubyObject
113
113
  {
114
114
  if ( stack.size() == 0 )
115
115
  {
116
- self.callMethod(
117
- context,
118
- "unexpected_input_error",
119
- token
120
- );
116
+ IRubyObject[] error_args = {
117
+ RubyFixnum.newFixnum(self.runtime, -1),
118
+ RubyFixnum.newFixnum(self.runtime, -1),
119
+ type,
120
+ value
121
+ };
122
+
123
+ self.callMethod(context, "parser_error", error_args);
121
124
  }
122
125
 
123
126
  Long stack_value = stack.pop();
@@ -138,16 +141,14 @@ public class Driver extends RubyObject
138
141
 
139
142
  if ( production_i == self.T_EOF )
140
143
  {
141
- IRubyObject[] stack_input_error_args = {
144
+ IRubyObject[] error_args = {
145
+ RubyFixnum.newFixnum(self.runtime, stack_type),
142
146
  RubyFixnum.newFixnum(self.runtime, stack_value),
143
- token
147
+ type,
148
+ value
144
149
  };
145
150
 
146
- self.callMethod(
147
- context,
148
- "stack_input_error",
149
- stack_input_error_args
150
- );
151
+ self.callMethod(context, "parser_error", error_args);
151
152
  }
152
153
  else
153
154
  {
@@ -171,16 +172,14 @@ public class Driver extends RubyObject
171
172
  }
172
173
  else
173
174
  {
174
- IRubyObject[] invalid_terminal_args = {
175
- RubyFixnum.newFixnum(self.runtime, token_id),
176
- RubyFixnum.newFixnum(self.runtime, stack_value)
175
+ IRubyObject[] error_args = {
176
+ RubyFixnum.newFixnum(self.runtime, stack_type),
177
+ RubyFixnum.newFixnum(self.runtime, stack_value),
178
+ type,
179
+ value
177
180
  };
178
181
 
179
- self.callMethod(
180
- context,
181
- "invalid_terminal_error",
182
- invalid_terminal_args
183
- );
182
+ self.callMethod(context, "parser_error", error_args);
184
183
  }
185
184
  }
186
185
  // Action
@@ -0,0 +1,326 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.12
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+ module LL
9
+ module Bootstrap
10
+ class Parser < Racc::Parser
11
+
12
+ ##
13
+ # @see [LL::Lexer#initialize]
14
+ #
15
+ def initialize(*args)
16
+ @lexer = Lexer.new(*args)
17
+ end
18
+
19
+ ##
20
+ # Yields the next token from the lexer.
21
+ #
22
+ # @yieldparam [Array]
23
+ #
24
+ def yield_next_token
25
+ @lexer.advance do |token|
26
+ yield [token.type, token]
27
+ end
28
+
29
+ yield [false, false]
30
+ end
31
+
32
+ ##
33
+ # @see [LL::AST::Node#initialize]
34
+ # @return [LL::AST::Node]
35
+ #
36
+ def s(*args)
37
+ return AST::Node.new(*args)
38
+ end
39
+
40
+ ##
41
+ # Parses the input and returns the corresponding AST.
42
+ #
43
+ # @return [LL::AST::Node]
44
+ #
45
+ def parse
46
+ return yyparse(self, :yield_next_token)
47
+ end
48
+
49
+ # vim: set ft=racc:
50
+ ##### State transition tables begin ###
51
+
52
+ racc_action_table = [
53
+ 14, 28, 16, 14, 26, 29, 10, 11, 12, 13,
54
+ 14, 10, 11, 12, 13, 14, 14, 14, 14, 22,
55
+ 33, 33, 22, 24, 25, 37, 38, 14, 22, 40,
56
+ 41, 14, 28 ]
57
+
58
+ racc_action_check = [
59
+ 19, 18, 1, 10, 18, 19, 0, 0, 0, 0,
60
+ 0, 2, 2, 2, 2, 2, 24, 40, 11, 12,
61
+ 24, 40, 13, 15, 16, 27, 28, 31, 34, 35,
62
+ 36, 38, 42 ]
63
+
64
+ racc_action_pointer = [
65
+ 3, 2, 8, nil, nil, nil, nil, nil, nil, nil,
66
+ -4, 11, 17, 20, nil, 15, 24, nil, -8, -7,
67
+ nil, nil, nil, nil, 9, nil, nil, 13, 17, nil,
68
+ nil, 20, nil, nil, 26, 19, 18, nil, 24, nil,
69
+ 10, nil, 23, nil, nil ]
70
+
71
+ racc_action_default = [
72
+ -2, -30, -1, -4, -5, -6, -7, -8, -9, -10,
73
+ -30, -30, -30, -30, -20, -30, -30, -3, -30, -30,
74
+ -18, -16, -29, -17, -30, 45, -11, -30, -30, -15,
75
+ -19, -21, -22, -23, -24, -26, -30, -12, -30, -25,
76
+ -30, -28, -13, -27, -14 ]
77
+
78
+ racc_goto_table = [
79
+ 15, 27, 15, 1, 21, 23, 36, 3, 2, 17,
80
+ 18, 19, nil, nil, nil, nil, nil, nil, nil, 30,
81
+ nil, nil, 43, nil, nil, 44, 39, nil, nil, nil,
82
+ nil, 30, nil, nil, nil, nil, nil, nil, 42 ]
83
+
84
+ racc_goto_check = [
85
+ 10, 11, 10, 1, 13, 13, 17, 3, 2, 3,
86
+ 10, 12, nil, nil, nil, nil, nil, nil, nil, 10,
87
+ nil, nil, 17, nil, nil, 11, 13, nil, nil, nil,
88
+ nil, 10, nil, nil, nil, nil, nil, nil, 10 ]
89
+
90
+ racc_goto_pointer = [
91
+ nil, 3, 8, 7, nil, nil, nil, nil, nil, nil,
92
+ 0, -17, 0, -8, nil, nil, nil, -18 ]
93
+
94
+ racc_goto_default = [
95
+ nil, nil, nil, nil, 4, 5, 6, 7, 8, 9,
96
+ 20, nil, 31, nil, 34, 32, 35, nil ]
97
+
98
+ racc_reduce_table = [
99
+ 0, 0, :racc_error,
100
+ 1, 14, :_reduce_1,
101
+ 0, 14, :_reduce_2,
102
+ 2, 15, :_reduce_3,
103
+ 1, 15, :_reduce_4,
104
+ 1, 16, :_reduce_none,
105
+ 1, 16, :_reduce_none,
106
+ 1, 17, :_reduce_none,
107
+ 1, 17, :_reduce_none,
108
+ 1, 17, :_reduce_none,
109
+ 1, 17, :_reduce_none,
110
+ 3, 19, :_reduce_11,
111
+ 4, 19, :_reduce_12,
112
+ 3, 24, :_reduce_13,
113
+ 4, 24, :_reduce_14,
114
+ 3, 20, :_reduce_15,
115
+ 2, 21, :_reduce_16,
116
+ 2, 22, :_reduce_17,
117
+ 1, 25, :_reduce_18,
118
+ 2, 25, :_reduce_19,
119
+ 1, 23, :_reduce_20,
120
+ 1, 27, :_reduce_21,
121
+ 1, 27, :_reduce_22,
122
+ 1, 28, :_reduce_23,
123
+ 1, 29, :_reduce_24,
124
+ 2, 29, :_reduce_25,
125
+ 1, 30, :_reduce_26,
126
+ 3, 30, :_reduce_27,
127
+ 4, 18, :_reduce_28,
128
+ 1, 26, :_reduce_29 ]
129
+
130
+ racc_reduce_n = 30
131
+
132
+ racc_shift_n = 45
133
+
134
+ racc_token_table = {
135
+ false => 0,
136
+ :error => 1,
137
+ :T_RUBY => 2,
138
+ :T_NAME => 3,
139
+ :T_TERMINALS => 4,
140
+ :T_INNER => 5,
141
+ :T_HEADER => 6,
142
+ :T_IDENT => 7,
143
+ :T_EQUALS => 8,
144
+ :T_COLON => 9,
145
+ :T_PIPE => 10,
146
+ :T_EPSILON => 11,
147
+ :T_SEMICOLON => 12 }
148
+
149
+ racc_nt_base = 13
150
+
151
+ racc_use_result_var = false
152
+
153
+ Racc_arg = [
154
+ racc_action_table,
155
+ racc_action_check,
156
+ racc_action_default,
157
+ racc_action_pointer,
158
+ racc_goto_table,
159
+ racc_goto_check,
160
+ racc_goto_default,
161
+ racc_goto_pointer,
162
+ racc_nt_base,
163
+ racc_reduce_table,
164
+ racc_token_table,
165
+ racc_shift_n,
166
+ racc_reduce_n,
167
+ racc_use_result_var ]
168
+
169
+ Racc_token_to_s_table = [
170
+ "$end",
171
+ "error",
172
+ "T_RUBY",
173
+ "T_NAME",
174
+ "T_TERMINALS",
175
+ "T_INNER",
176
+ "T_HEADER",
177
+ "T_IDENT",
178
+ "T_EQUALS",
179
+ "T_COLON",
180
+ "T_PIPE",
181
+ "T_EPSILON",
182
+ "T_SEMICOLON",
183
+ "$start",
184
+ "grammar",
185
+ "elements",
186
+ "element",
187
+ "directive",
188
+ "rule",
189
+ "name",
190
+ "terminals",
191
+ "inner",
192
+ "header",
193
+ "ident",
194
+ "name_ns",
195
+ "idents",
196
+ "ruby",
197
+ "idents_or_epsilon",
198
+ "epsilon",
199
+ "branch",
200
+ "branches" ]
201
+
202
+ Racc_debug_parser = false
203
+
204
+ ##### State transition tables end #####
205
+
206
+ # reduce 0 omitted
207
+
208
+ def _reduce_1(val, _values)
209
+ s(:grammar, val[0])
210
+ end
211
+
212
+ def _reduce_2(val, _values)
213
+ s(:grammar)
214
+ end
215
+
216
+ def _reduce_3(val, _values)
217
+ val[0] << val[1]
218
+ end
219
+
220
+ def _reduce_4(val, _values)
221
+ val
222
+ end
223
+
224
+ # reduce 5 omitted
225
+
226
+ # reduce 6 omitted
227
+
228
+ # reduce 7 omitted
229
+
230
+ # reduce 8 omitted
231
+
232
+ # reduce 9 omitted
233
+
234
+ # reduce 10 omitted
235
+
236
+ def _reduce_11(val, _values)
237
+ s(:name, [val[1]], :source_line => val[0].source_line)
238
+
239
+ end
240
+
241
+ def _reduce_12(val, _values)
242
+ s(:name, [val[1], *val[2]], :source_line => val[0].source_line)
243
+
244
+ end
245
+
246
+ def _reduce_13(val, _values)
247
+ [val[2]]
248
+ end
249
+
250
+ def _reduce_14(val, _values)
251
+ [val[2]] + val[3]
252
+ end
253
+
254
+ def _reduce_15(val, _values)
255
+ s(:terminals, val[1], :source_line => val[0].source_line)
256
+
257
+ end
258
+
259
+ def _reduce_16(val, _values)
260
+ s(:inner, [val[1]], :source_line => val[0].source_line)
261
+ end
262
+
263
+ def _reduce_17(val, _values)
264
+ s(:header, [val[1]], :source_line => val[0].source_line)
265
+ end
266
+
267
+ def _reduce_18(val, _values)
268
+ val
269
+ end
270
+
271
+ def _reduce_19(val, _values)
272
+ val[0] << val[1]
273
+ end
274
+
275
+ def _reduce_20(val, _values)
276
+ s(:ident, [val[0].value], :source_line => val[0].source_line)
277
+ end
278
+
279
+ def _reduce_21(val, _values)
280
+ s(:steps, val[0], :source_line => val[0][0].source_line)
281
+
282
+ end
283
+
284
+ def _reduce_22(val, _values)
285
+ s(:steps, [val[0]], :source_line => val[0].source_line)
286
+
287
+ end
288
+
289
+ def _reduce_23(val, _values)
290
+ s(:epsilon, [], :source_line => val[0].source_line)
291
+ end
292
+
293
+ def _reduce_24(val, _values)
294
+ s(:branch, [val[0]], :source_line => val[0].source_line)
295
+
296
+ end
297
+
298
+ def _reduce_25(val, _values)
299
+ s(:branch, [val[0], val[1]], :source_line => val[0].source_line)
300
+
301
+ end
302
+
303
+ def _reduce_26(val, _values)
304
+ val
305
+ end
306
+
307
+ def _reduce_27(val, _values)
308
+ [val[0]] + val[2]
309
+ end
310
+
311
+ def _reduce_28(val, _values)
312
+ s(:rule, [val[0], *val[2]], :source_line => val[0].source_line)
313
+
314
+ end
315
+
316
+ def _reduce_29(val, _values)
317
+ s(:ruby, [val[0].value], :source_line => val[0].source_line)
318
+ end
319
+
320
+ def _reduce_none(val, _values)
321
+ val[0]
322
+ end
323
+
324
+ end # class Parser
325
+ end # module Bootstrap
326
+ end # module LL
@@ -8,6 +8,7 @@ module LL
8
8
  # @return [Hash]
9
9
  #
10
10
  TYPES = {
11
+ :eof => -1,
11
12
  :rule => 0,
12
13
  :terminal => 1,
13
14
  :epsilon => 2,
data/lib/ll/driver.rb CHANGED
@@ -4,43 +4,58 @@ module LL
4
4
  #
5
5
  class Driver
6
6
  ##
7
- # Error method that is called when no rule was found for a table index.
7
+ # @param [Fixnum] stack_type
8
+ # @param [Fixnum] stack_value
9
+ # @param [Symbol] token_type
10
+ # @param [Mixed] token_value
8
11
  #
12
+ def parser_error(stack_type, stack_value, token_type, token_value)
13
+ message = parser_error_message(stack_type, stack_value, token_type)
14
+
15
+ raise ParserError, message
16
+ end
17
+
18
+ ##
19
+ # @param [Fixnum] stack_type
9
20
  # @param [Fixnum] stack_value
10
- # @param [Array] token
21
+ # @param [Symbol] token_type
22
+ # @return [String]
11
23
  #
12
- def stack_input_error(stack_value, token)
13
- type = token[0].inspect
24
+ def parser_error_message(stack_type, stack_value, token_type)
25
+ case id_to_type(stack_type)
26
+ when :rule
27
+ message = "Unexpected #{token_type} for rule #{stack_value}"
28
+ when :terminal
29
+ expected = id_to_terminal(stack_value)
30
+ message = "Unexpected #{token_type}, expected #{expected} instead"
31
+ when :eof
32
+ message = "Received #{token_type} but there's nothing left to parse"
33
+ end
14
34
 
15
- raise ParserError, "Unexpected rule #{stack_value} for #{type}"
35
+ return message
16
36
  end
17
37
 
18
38
  ##
19
- # Error method that is called when the stack has been consumed but there's
20
- # still input being sent to the parser.
39
+ # Returns the Symbol that belongs to the stack type number.
40
+ #
41
+ # @example
42
+ # id_to_type(1) # => :terminal
21
43
  #
22
- # @param [Array] token
44
+ # @param [Fixnum] id
45
+ # @return [Symbol]
23
46
  #
24
- def unexpected_input_error(token)
25
- raise(
26
- ParserError,
27
- "Received token #{token[0].inspect} but there's nothing left to parse"
28
- )
47
+ def id_to_type(id)
48
+ return ConfigurationCompiler::TYPES.invert[id]
29
49
  end
30
50
 
31
51
  ##
32
- # Error method that is called when an invalid terminal was specified as the
33
- # input.
52
+ # Returns the Symbol of the terminal index.
34
53
  #
35
- # @param [Fixnum] got_id The ID of the received terminal.
36
- # @param [Fixnum] expected_id The ID of the expected terminal.
54
+ # @param [Fixnum] id
55
+ # @return [Symbol]
37
56
  #
38
- def invalid_terminal_error(got_id, expected_id)
39
- terminals = self.class::CONFIG.terminals
40
- expected = terminals[expected_id].inspect
41
- got = terminals[got_id].inspect
42
-
43
- raise ParserError, "Invalid terminal #{got}, expected #{expected}"
57
+ def id_to_terminal(id)
58
+ return self.class::CONFIG.terminals[id]
44
59
  end
45
60
  end # Driver
46
61
  end # LL
data/lib/ll/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LL
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end # LL
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: 1.0.0
4
+ version: 1.1.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-02-12 00:00:00.000000000 Z
11
+ date: 2015-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast
@@ -166,6 +166,7 @@ files:
166
166
  - ext/java/org/libll/DriverConfig.java
167
167
  - lib/ll.rb
168
168
  - lib/ll/ast/node.rb
169
+ - lib/ll/bootstrap/parser.rb
169
170
  - lib/ll/branch.rb
170
171
  - lib/ll/cli.rb
171
172
  - lib/ll/code_generator.rb