antelope 0.2.4 → 0.3.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.
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