antelope 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -0
  3. data/bin/antelope +3 -3
  4. data/examples/{example.err → example.ace.err} +9 -9
  5. data/examples/{example.inf → example.ace.inf} +57 -9
  6. data/examples/example.ate +70 -0
  7. data/examples/example.ate.err +192 -0
  8. data/examples/example.ate.inf +432 -0
  9. data/lib/antelope/ace/compiler.rb +4 -4
  10. data/lib/antelope/ace/errors.rb +0 -18
  11. data/lib/antelope/ace.rb +6 -12
  12. data/lib/antelope/cli.rb +1 -1
  13. data/lib/antelope/dsl/compiler.rb +117 -0
  14. data/lib/antelope/dsl/contexts/base.rb +29 -0
  15. data/lib/antelope/dsl/contexts/main.rb +63 -0
  16. data/lib/antelope/dsl/contexts/match.rb +24 -0
  17. data/lib/antelope/dsl/contexts/precedence.rb +20 -0
  18. data/lib/antelope/dsl/contexts/production.rb +24 -0
  19. data/lib/antelope/dsl/contexts/terminal.rb +28 -0
  20. data/lib/antelope/dsl/contexts.rb +16 -0
  21. data/lib/antelope/dsl.rb +9 -0
  22. data/lib/antelope/errors.rb +18 -1
  23. data/lib/antelope/generation/constructor/first.rb +10 -12
  24. data/lib/antelope/generation/constructor/follow.rb +6 -6
  25. data/lib/antelope/generation/constructor/nullable.rb +6 -6
  26. data/lib/antelope/generation/constructor.rb +4 -4
  27. data/lib/antelope/generation/recognizer/rule.rb +17 -17
  28. data/lib/antelope/generation/recognizer/state.rb +9 -10
  29. data/lib/antelope/generation/recognizer.rb +8 -11
  30. data/lib/antelope/generation/tableizer.rb +2 -2
  31. data/lib/antelope/generator/base.rb +7 -7
  32. data/lib/antelope/generator/ruby.rb +1 -1
  33. data/lib/antelope/grammar/generation.rb +77 -0
  34. data/lib/antelope/grammar/loading.rb +84 -0
  35. data/lib/antelope/{ace → grammar}/precedence.rb +2 -4
  36. data/lib/antelope/grammar/precedences.rb +64 -0
  37. data/lib/antelope/{ace → grammar}/production.rb +11 -12
  38. data/lib/antelope/grammar/productions.rb +154 -0
  39. data/lib/antelope/grammar/symbols.rb +64 -0
  40. data/lib/antelope/{ace → grammar}/token/epsilon.rb +1 -2
  41. data/lib/antelope/{ace → grammar}/token/error.rb +1 -3
  42. data/lib/antelope/{ace → grammar}/token/nonterminal.rb +1 -3
  43. data/lib/antelope/{ace → grammar}/token/terminal.rb +1 -3
  44. data/lib/antelope/{ace → grammar}/token.rb +12 -15
  45. data/lib/antelope/grammar.rb +68 -0
  46. data/lib/antelope/version.rb +1 -1
  47. data/lib/antelope.rb +12 -6
  48. data/spec/antelope/ace/compiler_spec.rb +6 -6
  49. data/spec/antelope/ace/scanner_spec.rb +7 -7
  50. data/spec/antelope/generation/constructor_spec.rb +131 -0
  51. data/spec/support/grammar_helper.rb +2 -3
  52. metadata +32 -19
  53. data/lib/antelope/ace/grammar/generation.rb +0 -80
  54. data/lib/antelope/ace/grammar/loading.rb +0 -53
  55. data/lib/antelope/ace/grammar/precedences.rb +0 -68
  56. data/lib/antelope/ace/grammar/productions.rb +0 -156
  57. data/lib/antelope/ace/grammar/symbols.rb +0 -66
  58. data/lib/antelope/ace/grammar.rb +0 -69
  59. data/spec/antelope/constructor_spec.rb +0 -133
@@ -0,0 +1,432 @@
1
+ Productions:
2
+ 15/n1: expression → NUMBER { match[0][1] }
3
+ 26/n0: $start → expression $end
4
+ 79/r4: expression → expression "^" expression { match[0] ** match[2] }
5
+ 85/l2: expression → expression "+" expression { match[0] + match[2] }
6
+ 91/l2: expression → expression "-" expression { match[0] - match[2] }
7
+ 97/l3: expression → expression "*" expression { match[0] * match[2] }
8
+ 103/l3: expression → expression "/" expression { match[0] / match[2] }
9
+ 109/n1: expression → "(" expression ")" { match[1] }
10
+ 110/n1: expression → "(" $error ")" { match[1] }
11
+
12
+
13
+ Precedence:
14
+ --- highest
15
+ right 4:
16
+ {EXPONENTIATE}
17
+ left 3:
18
+ {MULTIPLY, DIVIDE}
19
+ left 2:
20
+ {ADD, SUBTRACT}
21
+ nonassoc 1:
22
+ {_}
23
+ nonassoc 0:
24
+ {$end}
25
+ --- lowest
26
+
27
+ State 0:
28
+ 0/n0: $start → • expression $end
29
+ {}
30
+ 1/n1: expression → • NUMBER
31
+ {}
32
+ 2/r4: expression → • expression "^" expression
33
+ {}
34
+ 3/l2: expression → • expression "+" expression
35
+ {}
36
+ 4/l2: expression → • expression "-" expression
37
+ {}
38
+ 5/l3: expression → • expression "*" expression
39
+ {}
40
+ 6/l3: expression → • expression "/" expression
41
+ {}
42
+ 7/n1: expression → • "(" expression ")"
43
+ {}
44
+ 8/n1: expression → • "(" $error ")"
45
+ {}
46
+ 9/n0: $start → expression • $end
47
+ {}
48
+ 10/r4: expression → expression • "^" expression
49
+ {}
50
+ 11/l2: expression → expression • "+" expression
51
+ {}
52
+ 12/l2: expression → expression • "-" expression
53
+ {}
54
+ 13/l3: expression → expression • "*" expression
55
+ {}
56
+ 14/l3: expression → expression • "/" expression
57
+ {}
58
+ 15/n1: expression → NUMBER •
59
+ {$end, "^", "+", "-", "*", "/", ")"}
60
+ 16/n1: expression → "(" • expression ")"
61
+ {}
62
+ 17/n1: expression → "(" • $error ")"
63
+ {}
64
+ 26/n0: $start → expression $end •
65
+ {}
66
+ 27/r4: expression → expression "^" • expression
67
+ {}
68
+ 36/l2: expression → expression "+" • expression
69
+ {}
70
+ 45/l2: expression → expression "-" • expression
71
+ {}
72
+ 54/l3: expression → expression "*" • expression
73
+ {}
74
+ 63/l3: expression → expression "/" • expression
75
+ {}
76
+ 72/n1: expression → "(" expression • ")"
77
+ {}
78
+ 78/n1: expression → "(" $error • ")"
79
+ {}
80
+ 79/r4: expression → expression "^" expression •
81
+ {$end, "^", "+", "-", "*", "/", ")"}
82
+ 85/l2: expression → expression "+" expression •
83
+ {$end, "^", "+", "-", "*", "/", ")"}
84
+ 91/l2: expression → expression "-" expression •
85
+ {$end, "^", "+", "-", "*", "/", ")"}
86
+ 97/l3: expression → expression "*" expression •
87
+ {$end, "^", "+", "-", "*", "/", ")"}
88
+ 103/l3: expression → expression "/" expression •
89
+ {$end, "^", "+", "-", "*", "/", ")"}
90
+ 109/n1: expression → "(" expression ")" •
91
+ {$end, "^", "+", "-", "*", "/", ")"}
92
+ 110/n1: expression → "(" $error ")" •
93
+ {$end, "^", "+", "-", "*", "/", ")"}
94
+ transitions:
95
+ expression: State 1
96
+ NUMBER: State 2
97
+ "(": State 3
98
+
99
+ State 1:
100
+ 9/n0: $start → expression • $end
101
+ {}
102
+ 10/r4: expression → expression • "^" expression
103
+ {}
104
+ 11/l2: expression → expression • "+" expression
105
+ {}
106
+ 12/l2: expression → expression • "-" expression
107
+ {}
108
+ 13/l3: expression → expression • "*" expression
109
+ {}
110
+ 14/l3: expression → expression • "/" expression
111
+ {}
112
+ transitions:
113
+ $end: State 4
114
+ "^": State 5
115
+ "+": State 6
116
+ "-": State 7
117
+ "*": State 8
118
+ "/": State 9
119
+
120
+ State 2:
121
+ 15/n1: expression → NUMBER •
122
+ {$end, "^", "+", "-", "*", "/", ")"}
123
+ reductions:
124
+ $default: Rule 1
125
+
126
+ State 3:
127
+ 16/n1: expression → "(" • expression ")"
128
+ {}
129
+ 17/n1: expression → "(" • $error ")"
130
+ {}
131
+ 18/n1: expression → • NUMBER
132
+ {}
133
+ 19/r4: expression → • expression "^" expression
134
+ {}
135
+ 20/l2: expression → • expression "+" expression
136
+ {}
137
+ 21/l2: expression → • expression "-" expression
138
+ {}
139
+ 22/l3: expression → • expression "*" expression
140
+ {}
141
+ 23/l3: expression → • expression "/" expression
142
+ {}
143
+ 24/n1: expression → • "(" expression ")"
144
+ {}
145
+ 25/n1: expression → • "(" $error ")"
146
+ {}
147
+ transitions:
148
+ expression: State 10
149
+ $error: State 11
150
+ NUMBER: State 2
151
+ "(": State 3
152
+
153
+ State 4:
154
+ 26/n0: $start → expression $end •
155
+ {}
156
+ accepting:
157
+ $end: Rule 0
158
+
159
+ State 5:
160
+ 27/r4: expression → expression "^" • expression
161
+ {}
162
+ 28/n1: expression → • NUMBER
163
+ {}
164
+ 29/r4: expression → • expression "^" expression
165
+ {}
166
+ 30/l2: expression → • expression "+" expression
167
+ {}
168
+ 31/l2: expression → • expression "-" expression
169
+ {}
170
+ 32/l3: expression → • expression "*" expression
171
+ {}
172
+ 33/l3: expression → • expression "/" expression
173
+ {}
174
+ 34/n1: expression → • "(" expression ")"
175
+ {}
176
+ 35/n1: expression → • "(" $error ")"
177
+ {}
178
+ transitions:
179
+ expression: State 12
180
+ NUMBER: State 2
181
+ "(": State 3
182
+
183
+ State 6:
184
+ 36/l2: expression → expression "+" • expression
185
+ {}
186
+ 37/n1: expression → • NUMBER
187
+ {}
188
+ 38/r4: expression → • expression "^" expression
189
+ {}
190
+ 39/l2: expression → • expression "+" expression
191
+ {}
192
+ 40/l2: expression → • expression "-" expression
193
+ {}
194
+ 41/l3: expression → • expression "*" expression
195
+ {}
196
+ 42/l3: expression → • expression "/" expression
197
+ {}
198
+ 43/n1: expression → • "(" expression ")"
199
+ {}
200
+ 44/n1: expression → • "(" $error ")"
201
+ {}
202
+ transitions:
203
+ expression: State 13
204
+ NUMBER: State 2
205
+ "(": State 3
206
+
207
+ State 7:
208
+ 45/l2: expression → expression "-" • expression
209
+ {}
210
+ 46/n1: expression → • NUMBER
211
+ {}
212
+ 47/r4: expression → • expression "^" expression
213
+ {}
214
+ 48/l2: expression → • expression "+" expression
215
+ {}
216
+ 49/l2: expression → • expression "-" expression
217
+ {}
218
+ 50/l3: expression → • expression "*" expression
219
+ {}
220
+ 51/l3: expression → • expression "/" expression
221
+ {}
222
+ 52/n1: expression → • "(" expression ")"
223
+ {}
224
+ 53/n1: expression → • "(" $error ")"
225
+ {}
226
+ transitions:
227
+ expression: State 14
228
+ NUMBER: State 2
229
+ "(": State 3
230
+
231
+ State 8:
232
+ 54/l3: expression → expression "*" • expression
233
+ {}
234
+ 55/n1: expression → • NUMBER
235
+ {}
236
+ 56/r4: expression → • expression "^" expression
237
+ {}
238
+ 57/l2: expression → • expression "+" expression
239
+ {}
240
+ 58/l2: expression → • expression "-" expression
241
+ {}
242
+ 59/l3: expression → • expression "*" expression
243
+ {}
244
+ 60/l3: expression → • expression "/" expression
245
+ {}
246
+ 61/n1: expression → • "(" expression ")"
247
+ {}
248
+ 62/n1: expression → • "(" $error ")"
249
+ {}
250
+ transitions:
251
+ expression: State 15
252
+ NUMBER: State 2
253
+ "(": State 3
254
+
255
+ State 9:
256
+ 63/l3: expression → expression "/" • expression
257
+ {}
258
+ 64/n1: expression → • NUMBER
259
+ {}
260
+ 65/r4: expression → • expression "^" expression
261
+ {}
262
+ 66/l2: expression → • expression "+" expression
263
+ {}
264
+ 67/l2: expression → • expression "-" expression
265
+ {}
266
+ 68/l3: expression → • expression "*" expression
267
+ {}
268
+ 69/l3: expression → • expression "/" expression
269
+ {}
270
+ 70/n1: expression → • "(" expression ")"
271
+ {}
272
+ 71/n1: expression → • "(" $error ")"
273
+ {}
274
+ transitions:
275
+ expression: State 16
276
+ NUMBER: State 2
277
+ "(": State 3
278
+
279
+ State 10:
280
+ 72/n1: expression → "(" expression • ")"
281
+ {}
282
+ 73/r4: expression → expression • "^" expression
283
+ {}
284
+ 74/l2: expression → expression • "+" expression
285
+ {}
286
+ 75/l2: expression → expression • "-" expression
287
+ {}
288
+ 76/l3: expression → expression • "*" expression
289
+ {}
290
+ 77/l3: expression → expression • "/" expression
291
+ {}
292
+ transitions:
293
+ ")": State 17
294
+ "^": State 5
295
+ "+": State 6
296
+ "-": State 7
297
+ "*": State 8
298
+ "/": State 9
299
+
300
+ State 11:
301
+ 78/n1: expression → "(" $error • ")"
302
+ {}
303
+ transitions:
304
+ ")": State 18
305
+
306
+ State 12:
307
+ 79/r4: expression → expression "^" expression •
308
+ {$end, "^", "+", "-", "*", "/", ")"}
309
+ 80/r4: expression → expression • "^" expression
310
+ {}
311
+ 81/l2: expression → expression • "+" expression
312
+ {}
313
+ 82/l2: expression → expression • "-" expression
314
+ {}
315
+ 83/l3: expression → expression • "*" expression
316
+ {}
317
+ 84/l3: expression → expression • "/" expression
318
+ {}
319
+ transitions:
320
+ "^": State 5
321
+ reductions:
322
+ "+": Rule 2
323
+ "-": Rule 2
324
+ "*": Rule 2
325
+ "/": Rule 2
326
+ $end: Rule 2
327
+ ")": Rule 2
328
+
329
+ State 13:
330
+ 85/l2: expression → expression "+" expression •
331
+ {$end, "^", "+", "-", "*", "/", ")"}
332
+ 86/r4: expression → expression • "^" expression
333
+ {}
334
+ 87/l2: expression → expression • "+" expression
335
+ {}
336
+ 88/l2: expression → expression • "-" expression
337
+ {}
338
+ 89/l3: expression → expression • "*" expression
339
+ {}
340
+ 90/l3: expression → expression • "/" expression
341
+ {}
342
+ transitions:
343
+ "^": State 5
344
+ "*": State 8
345
+ "/": State 9
346
+ reductions:
347
+ "+": Rule 3
348
+ "-": Rule 3
349
+ $end: Rule 3
350
+ ")": Rule 3
351
+
352
+ State 14:
353
+ 91/l2: expression → expression "-" expression •
354
+ {$end, "^", "+", "-", "*", "/", ")"}
355
+ 92/r4: expression → expression • "^" expression
356
+ {}
357
+ 93/l2: expression → expression • "+" expression
358
+ {}
359
+ 94/l2: expression → expression • "-" expression
360
+ {}
361
+ 95/l3: expression → expression • "*" expression
362
+ {}
363
+ 96/l3: expression → expression • "/" expression
364
+ {}
365
+ transitions:
366
+ "^": State 5
367
+ "*": State 8
368
+ "/": State 9
369
+ reductions:
370
+ "+": Rule 4
371
+ "-": Rule 4
372
+ $end: Rule 4
373
+ ")": Rule 4
374
+
375
+ State 15:
376
+ 97/l3: expression → expression "*" expression •
377
+ {$end, "^", "+", "-", "*", "/", ")"}
378
+ 98/r4: expression → expression • "^" expression
379
+ {}
380
+ 99/l2: expression → expression • "+" expression
381
+ {}
382
+ 100/l2: expression → expression • "-" expression
383
+ {}
384
+ 101/l3: expression → expression • "*" expression
385
+ {}
386
+ 102/l3: expression → expression • "/" expression
387
+ {}
388
+ transitions:
389
+ "^": State 5
390
+ reductions:
391
+ "+": Rule 5
392
+ "-": Rule 5
393
+ "*": Rule 5
394
+ "/": Rule 5
395
+ $end: Rule 5
396
+ ")": Rule 5
397
+
398
+ State 16:
399
+ 103/l3: expression → expression "/" expression •
400
+ {$end, "^", "+", "-", "*", "/", ")"}
401
+ 104/r4: expression → expression • "^" expression
402
+ {}
403
+ 105/l2: expression → expression • "+" expression
404
+ {}
405
+ 106/l2: expression → expression • "-" expression
406
+ {}
407
+ 107/l3: expression → expression • "*" expression
408
+ {}
409
+ 108/l3: expression → expression • "/" expression
410
+ {}
411
+ transitions:
412
+ "^": State 5
413
+ reductions:
414
+ "+": Rule 6
415
+ "-": Rule 6
416
+ "*": Rule 6
417
+ "/": Rule 6
418
+ $end: Rule 6
419
+ ")": Rule 6
420
+
421
+ State 17:
422
+ 109/n1: expression → "(" expression ")" •
423
+ {$end, "^", "+", "-", "*", "/", ")"}
424
+ reductions:
425
+ $default: Rule 7
426
+
427
+ State 18:
428
+ 110/n1: expression → "(" $error ")" •
429
+ {$end, "^", "+", "-", "*", "/", ")"}
430
+ reductions:
431
+ $default: Rule 8
432
+
@@ -53,7 +53,7 @@ module Antelope
53
53
 
54
54
  # Options defined by directives in the first part of the file.
55
55
  #
56
- # - **`:terminals`** (`Array<Symbol, String?)>)` &mdash; A list
56
+ # - **`:terminals`** (`Array<Symbol, String?>)` &mdash; A list
57
57
  # of all of the terminals in the language. If this is not
58
58
  # properly defined, the grammar will throw an error saying
59
59
  # that a symbol used in the grammar is not defined.
@@ -105,9 +105,9 @@ module Antelope
105
105
  # Pretty inspect.
106
106
  #
107
107
  # @return [String]
108
- def inspect
109
- "#<#{self.class} state=#{@state.inspect} options=#{options.inspect}>"
110
- end
108
+ # def inspect
109
+ # "#<#{self.class} state=#{@state.inspect} options=#{options.inspect}>"
110
+ # end
111
111
 
112
112
  # Runs the compiler on the input tokens. For each token,
113
113
  # it calls `compile_<type>` with `<type>` being the first
@@ -9,35 +9,17 @@ module Antelope
9
9
  class Error < Antelope::Error
10
10
  end
11
11
 
12
- # Used primarily in the {Compiler}, this is raised when the
13
- # version requirement of the Ace file doesn't match the running
14
- # version of Ace.
15
- class IncompatibleVersionError < Error
16
- end
17
-
18
12
  # Used primarily in the {Scanner}, this is raised when an input
19
13
  # is malformed. The message should contain a snippet of the input
20
14
  # which caused the error.
21
15
  class SyntaxError < Error
22
16
  end
23
17
 
24
- # This is used primarily in the {Grammar}; if a rule references a
25
- # token (a nonterminal or a terminal) that was not previously
26
- # defined, this is raised.
27
- class UndefinedTokenError < Error
28
- end
29
-
30
18
  # Primarily used in the {Compiler}, if a scanner token appears
31
19
  # that should not be in the current state, this is raised.
32
20
  class InvalidStateError < Error
33
21
  end
34
22
 
35
- # Primarily used in the {Grammar} (specifically
36
- # {Grammar::Generation}), if the grammar could not determine the
37
- # generator to use for the generation, it raises this.
38
- class NoTypeError < Error
39
- end
40
-
41
23
  # Primarily used in the {Compiler}, it is raised if it encounters
42
24
  # a directive it cannot handle. This is more to warn the
43
25
  # developer that a directive they wrote may not be accepted by any
data/lib/antelope/ace.rb CHANGED
@@ -1,15 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "antelope/ace/errors"
4
- require "antelope/ace/scanner"
5
- require "antelope/ace/compiler"
6
- require "antelope/ace/token"
7
- require "antelope/ace/precedence"
8
- require "antelope/ace/production"
9
- require "antelope/ace/grammar"
3
+ require 'antelope/ace/errors'
4
+ require 'antelope/ace/scanner'
5
+ require 'antelope/ace/compiler'
10
6
 
11
7
  module Antelope
12
-
13
8
  # Defines the Ace file. The Ace file format works similarly to
14
9
  # bison's y file format. The Ace file is seperated into three
15
10
  # parts:
@@ -27,18 +22,18 @@ module Antelope
27
22
  # %%
28
23
  #
29
24
  # The first part consists of _directives_ and _blocks_; directives
30
- # look something like `"%" <directive>[ <argument>]*\n`, with
25
+ # look something like `'%' <directive>[ <argument>]*\n`, with
31
26
  # `<directive>` being any alphanumerical character, including
32
27
  # underscores and dashes, and `<argument>` being any word character
33
28
  # or a quote-delimited string. Blocks consist of
34
- # `"%{" <content> "\n" "\s"* "%}"`, with `<content>` being any
29
+ # `'%{" <content> "\n" "\s"* "%}'`, with `<content>` being any
35
30
  # characters. The content is copied directly into the body of the
36
31
  # output.
37
32
  #
38
33
  # The second part consists of rules. Rules look something like
39
34
  # this:
40
35
  #
41
- # <nonterminal>: (<nonterminal> | <terminal>)* ["{" <content> "}"] ["|" (<nonterminal> | <terminal>)* ["{" <content> "}"]]* [;]
36
+ # <nonterminal>: (<nonterminal> | <terminal>)* ['{" <content> "}"] ["|" (<nonterminal> | <terminal>)* ["{" <content> "}']]* [;]
42
37
  #
43
38
  # Where `<nonterminal>` is any lowercase alphabetical cahracter,
44
39
  # `<terminal>` is any uppercase alphabetical character, and
@@ -48,6 +43,5 @@ module Antelope
48
43
  # The third part consists of a body, which is copied directly into
49
44
  # the output.
50
45
  module Ace
51
-
52
46
  end
53
47
  end
data/lib/antelope/cli.rb CHANGED
@@ -46,7 +46,7 @@ module Antelope
46
46
  def compile_file(file, gen = :guess)
47
47
  puts "Compiling #{file}... "
48
48
 
49
- grammar = Ace::Grammar.from_file(file)
49
+ grammar = Grammar.from_file(file)
50
50
  grammar.generate(options, gen)
51
51
 
52
52
  rescue => e
@@ -0,0 +1,117 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems/requirement'
4
+
5
+ module Antelope
6
+ module DSL
7
+ class Compiler
8
+ # The body of the output compiler. This should be formatted in
9
+ # the language that the parser is to be written in. Some output
10
+ # generators may have special syntax that allows the parser to
11
+ # be put in the body; see the output generators for more.
12
+ #
13
+ # For the DSL compiler, this is the :default template; if the
14
+ # :default template does not exist, the compilation will error.
15
+ #
16
+ # @return [String]
17
+ attr_reader :body
18
+
19
+ # A list of all the rules that are defined in the file. The
20
+ # rules are defined as such:
21
+ #
22
+ # - **`label`** (`Symbol`) &mdash; The left-hand side of the rule;
23
+ # this is the nonterminal that the right side reduces to.
24
+ # - **`set`** (`Array<Symbol>`) &mdash; The right-hand side of the
25
+ # rule. This is a combination of terminals and nonterminals.
26
+ # - **`block`** (`String`) &mdash; The code to be run on a reduction.
27
+ # this should be formatted in the language that the output
28
+ # parser is written in. Optional; default value is `""`.
29
+ # - **`prec`** (`String`) &mdash; The precedence level for the
30
+ # rule. This should be a nonterminal or terminal. Optional;
31
+ # default value is `""`.
32
+ #
33
+ # @return [Array<Hash>]
34
+ attr_reader :rules
35
+
36
+ # Options defined by the file itself.
37
+ #
38
+ # - **`:terminals`** (`Array<Symbol, String?)>)` &mdash; A list
39
+ # of all of the terminals in the language. If this is not
40
+ # properly defined, the grammar will throw an error saying
41
+ # that a symbol used in the grammar is not defined.
42
+ # - **`:prec`** (`Array<(Symbol, Array<Symbol>)>`) &mdash; A list
43
+ # of the precedence rules of the grammar. The first element
44
+ # of each element is the _type_ of precedence (and should be
45
+ # any of `:left`, `:right`, or `:nonassoc`), and the second
46
+ # element should be the symbols that are on that level.
47
+ # - **`:type`** (`String`) &mdash; The type of generator to
48
+ # generate; this should be a language.
49
+ # - **`:extra`** (`Hash<Symbol, Array<Object>>`) &mdash; Extra
50
+ # options that are not defined here.
51
+ # @return [Hash]
52
+ attr_reader :options
53
+
54
+ def self.compile(env = {}, &block)
55
+ new(env, &block).tap(&:compile)
56
+ end
57
+
58
+ def initialize(env = {}, &block)
59
+ @env = env
60
+ @options = {}
61
+ @block = block
62
+ end
63
+
64
+ def compile
65
+ call
66
+ handle_requirement
67
+ handle_rules
68
+ handle_options
69
+ @body = @context[:templates].fetch(:default)
70
+ end
71
+
72
+ def call
73
+ @context ||= Contexts::Main.new(options.fetch(:context, {}))
74
+ .call(&@block)
75
+ end
76
+
77
+ protected
78
+
79
+ def handle_requirement
80
+ required = @options.fetch(:require, ">= 0.0.0")
81
+ antelope_version = Gem::Version.new(Antelope::VERSION)
82
+ required_version = Gem::Requirement.new(required)
83
+
84
+ raise IncompatibleVersionError, "Grammar requires " \
85
+ "#{required}, have #{Antelope::VERSION}" unless
86
+ required_version =~ antelope_version
87
+ end
88
+
89
+ def handle_rules
90
+ @rules = []
91
+
92
+ @context[:productions].each do |label, rules|
93
+ rules.each do |rule|
94
+ @rules << { label: label,
95
+ set: rule[:body].map { |x| [x, nil] },
96
+ block: rule[:action],
97
+ prec: rule[:prec] }
98
+ end
99
+ end
100
+ end
101
+
102
+ def handle_options
103
+ @options[:prec] = @context[:precedences]
104
+ @options[:extra] = @context[:defines]
105
+ @options[:type] = @env[:output]
106
+ @options[:nonterminals] = []
107
+ @options[:terminals] = @context[:terminals].map do |name, value|
108
+ if value.is_a?(TrueClass)
109
+ [name.intern, nil, nil, nil]
110
+ else
111
+ [name.intern, nil, nil, value]
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,29 @@
1
+ module Antelope
2
+ module DSL
3
+ module Contexts
4
+ # The base context, which implements some helper methods.
5
+ class Base
6
+ attr_reader :options
7
+
8
+ def initialize(options)
9
+ @options = options
10
+ @contexts = Hash.new { |h, k| h[k] = k.new(@options) }
11
+ end
12
+
13
+ def call(&block)
14
+ before_call
15
+ instance_exec(self, &block)
16
+ data
17
+ end
18
+
19
+ def context(name, &block)
20
+ @contexts[name].call(&block)
21
+ end
22
+
23
+ def before_call; end
24
+
25
+ def data; end
26
+ end
27
+ end
28
+ end
29
+ end