antelope 0.2.0 → 0.2.2

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +25 -23
  3. data/.rspec +3 -3
  4. data/.travis.yml +10 -9
  5. data/.yardopts +7 -7
  6. data/CONTRIBUTING.md +38 -38
  7. data/GENERATORS.md +124 -124
  8. data/Gemfile +7 -7
  9. data/LICENSE.txt +22 -22
  10. data/README.md +104 -104
  11. data/Rakefile +2 -2
  12. data/TODO.md +58 -58
  13. data/antelope.gemspec +28 -28
  14. data/bin/antelope +7 -7
  15. data/examples/deterministic.ace +35 -35
  16. data/examples/example.ace +51 -50
  17. data/examples/example.err +192 -0
  18. data/examples/{example.output → example.inf} +384 -385
  19. data/examples/liquidscript.ace +233 -162
  20. data/examples/simple.ace +22 -22
  21. data/lib/antelope/ace/compiler.rb +334 -334
  22. data/lib/antelope/ace/errors.rb +48 -48
  23. data/lib/antelope/ace/grammar/generation.rb +80 -80
  24. data/lib/antelope/ace/grammar/loading.rb +53 -53
  25. data/lib/antelope/ace/grammar/precedences.rb +68 -65
  26. data/lib/antelope/ace/grammar/productions.rb +156 -150
  27. data/lib/antelope/ace/grammar/symbols.rb +66 -66
  28. data/lib/antelope/ace/grammar.rb +69 -69
  29. data/lib/antelope/ace/precedence.rb +61 -61
  30. data/lib/antelope/ace/production.rb +57 -57
  31. data/lib/antelope/ace/scanner/argument.rb +57 -57
  32. data/lib/antelope/ace/scanner/first.rb +89 -89
  33. data/lib/antelope/ace/scanner/second.rb +177 -177
  34. data/lib/antelope/ace/scanner/third.rb +27 -27
  35. data/lib/antelope/ace/scanner.rb +134 -134
  36. data/lib/antelope/ace/token/epsilon.rb +24 -24
  37. data/lib/antelope/ace/token/error.rb +26 -26
  38. data/lib/antelope/ace/token/nonterminal.rb +17 -17
  39. data/lib/antelope/ace/token/terminal.rb +17 -17
  40. data/lib/antelope/ace/token.rb +238 -238
  41. data/lib/antelope/ace.rb +53 -53
  42. data/lib/antelope/cli.rb +55 -55
  43. data/lib/antelope/errors.rb +8 -8
  44. data/lib/antelope/generation/constructor/first.rb +88 -88
  45. data/lib/antelope/generation/constructor/follow.rb +103 -103
  46. data/lib/antelope/generation/constructor/nullable.rb +64 -64
  47. data/lib/antelope/generation/constructor.rb +126 -126
  48. data/lib/antelope/generation/errors.rb +17 -17
  49. data/lib/antelope/generation/null.rb +13 -13
  50. data/lib/antelope/generation/recognizer/rule.rb +216 -216
  51. data/lib/antelope/generation/recognizer/state.rb +130 -130
  52. data/lib/antelope/generation/recognizer.rb +180 -180
  53. data/lib/antelope/generation/tableizer.rb +175 -154
  54. data/lib/antelope/generation.rb +15 -15
  55. data/lib/antelope/generator/base.rb +264 -264
  56. data/lib/antelope/generator/c.rb +11 -11
  57. data/lib/antelope/generator/c_header.rb +105 -105
  58. data/lib/antelope/generator/c_source.rb +39 -39
  59. data/lib/antelope/generator/error.rb +34 -0
  60. data/lib/antelope/generator/group.rb +57 -57
  61. data/lib/antelope/generator/html.rb +51 -0
  62. data/lib/antelope/generator/info.rb +47 -0
  63. data/lib/antelope/generator/null.rb +18 -18
  64. data/lib/antelope/generator/output.rb +17 -49
  65. data/lib/antelope/generator/ruby.rb +79 -79
  66. data/lib/antelope/generator/templates/c_header.ant +36 -36
  67. data/lib/antelope/generator/templates/c_source.ant +202 -202
  68. data/lib/antelope/generator/templates/error.ant +33 -0
  69. data/lib/antelope/generator/templates/html/antelope.css +1 -0
  70. data/lib/antelope/generator/templates/html/antelope.html +1 -0
  71. data/lib/antelope/generator/templates/html/antelope.js +1 -0
  72. data/lib/antelope/generator/templates/html/css.ant +53 -0
  73. data/lib/antelope/generator/templates/html/html.ant +82 -0
  74. data/lib/antelope/generator/templates/html/js.ant +9 -0
  75. data/lib/antelope/generator/templates/info.ant +53 -0
  76. data/lib/antelope/generator/templates/ruby.ant +178 -146
  77. data/lib/antelope/generator.rb +66 -63
  78. data/lib/antelope/template/compiler.rb +78 -78
  79. data/lib/antelope/template/errors.rb +9 -9
  80. data/lib/antelope/template/scanner.rb +109 -109
  81. data/lib/antelope/template.rb +65 -60
  82. data/lib/antelope/version.rb +6 -6
  83. data/lib/antelope.rb +13 -13
  84. data/optimizations.txt +42 -0
  85. data/spec/antelope/ace/compiler_spec.rb +60 -60
  86. data/spec/antelope/ace/scanner_spec.rb +27 -27
  87. data/spec/antelope/constructor_spec.rb +133 -136
  88. data/spec/antelope/template_spec.rb +50 -49
  89. data/spec/fixtures/simple.ace +22 -22
  90. data/spec/spec_helper.rb +39 -39
  91. data/spec/support/benchmark_helper.rb +5 -5
  92. data/spec/support/grammar_helper.rb +15 -15
  93. data/subl/Ace (Ruby).JSON-tmLanguage +94 -94
  94. data/subl/Ace (Ruby).tmLanguage +153 -153
  95. metadata +17 -6
  96. data/lib/antelope/generator/templates/output.ant +0 -68
@@ -0,0 +1,53 @@
1
+ body {
2
+ font-family: sans-serif;
3
+ color: #696265;
4
+ background-color: #fefefe;
5
+ }
6
+
7
+ h1, h2, h3, h4, h5, h6 {
8
+ font-family: serif;
9
+ color: #327CCB;
10
+ margin: 0;
11
+ }
12
+
13
+ code, kbd, pre {
14
+ font-family: monospace;
15
+ }
16
+
17
+ .body .section {
18
+ background-color: #f9f9f9;
19
+ padding: 0.5em;
20
+ }
21
+
22
+ .body .section h2 {
23
+ font-size: 1.5em;
24
+ }
25
+
26
+ .body .section h2, .body .section h3, .body .section h4,
27
+ .body .section h5, .body .section h6 {
28
+ padding: 0;
29
+ cursor: pointer;
30
+
31
+ }
32
+
33
+ .body .section .section-data {
34
+ display: none;
35
+ padding: 0.3em 2em;
36
+ }
37
+
38
+ .body .section .section-data.display {
39
+ display: block;
40
+ }
41
+
42
+ .body .section ul {
43
+ list-style-type: none;
44
+ }
45
+
46
+ .body .section ul, .body .section ol {
47
+ margin: 0;
48
+ padding: 0;
49
+ }
50
+
51
+ .conflict.resolved { color: #d9d9d9; }
52
+ .conflict.resolved:before { content: "resolved: "; color: #00B057; }
53
+ code.block { display: block; }
@@ -0,0 +1,82 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <title>Antelope State Data</title>
6
+
7
+ <meta charset="utf-8">
8
+ <link rel="stylesheet" type="text/css" href="%{file}.css">
9
+ </head>
10
+
11
+ <body>
12
+
13
+ <div class="body">
14
+ <div class="section productions">
15
+ <h2>Productions</h2>
16
+ <ol class="rules section-data">
17
+ {{ grammar.all_productions.each do |prod| }}
18
+ <li>
19
+ <code>{{= prod.label }}: {{= prod.items.join(' ') }}</code>
20
+ <code class="block">{{= prod.block }}</code>
21
+ </li>
22
+ {{ end }}
23
+ </ol>
24
+ </div>
25
+
26
+ <div class="section states">
27
+ <h2>States</h2>
28
+ <ul class="section-data">
29
+ {{ states = grammar.states.to_a }}
30
+ {{ table.each_with_index do |v, i| }}
31
+ <li class="section state">
32
+ {{ state = states[i] }}
33
+ <h3>State %{i}</h3>
34
+ <div class="section-data">
35
+ {{ state.rules.each do |rule| }}
36
+ <pre>{{= rule }}
37
+ {{= "{" << rule.lookahead.to_a.join(", ") << "}" }}</pre>
38
+ {{ end }}
39
+ {{
40
+ transitions = v.each.select { |_, a| a && a[0] == :state }
41
+ reductions = v.each.select { |_, a| a && a[0] == :reduce}
42
+ accepting = v.each.select { |_, a| a && a[0] == :accept}
43
+ conflicts = tableizer.conflicts[i].each
44
+ thing = [:transitions, :reductions, :accepting]
45
+ num_type = {
46
+ transitions: "State",
47
+ reductions: "Rule",
48
+ accepting: "Rule"
49
+ }
50
+ h = Hash[thing.zip([transitions, reductions, accepting])]
51
+ }}
52
+ {{ h.each do |key, value| }}
53
+ {{ next unless value.any? }}
54
+ <div class="part">
55
+ <h4>{{= key }}</h4>
56
+ {{ value.each do |token, (_, name)| }}
57
+ {{ token_value = grammar.terminals.find { |_| _.name == token } || token }}
58
+ <div>
59
+ <code>{{= token_value}}: {{= num_type[key] }} {{= name }}</code class="block"></div>
60
+ {{ end }}
61
+ </div>
62
+ {{ end }}
63
+ {{ if conflicts.any? }}
64
+ <div class="part">
65
+ <h4>Conflicts</h4>
66
+ {{ conflicts.each do |token, (value, first, second, rule, terminal)| }}
67
+ <div class="conflict {{ if value != 0 }}resolved{{ end }}">
68
+ <code>{{= token }}: {{= first.join(" ") }}/{{= second.join(" ") }} ({{= rule }} vs {{= terminal }})</code>
69
+ </div>
70
+ {{ end }}
71
+ </div>
72
+ {{ end }}
73
+ </div>
74
+ </li>
75
+ {{ end }}
76
+ </ul>
77
+ </div>
78
+ </div>
79
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
80
+ <script src="%{file}.js"></script>
81
+ </body>
82
+ </html>
@@ -0,0 +1,9 @@
1
+ $(function() {
2
+ $(".section").each(function(i, element) {
3
+ var $element = $(element);
4
+
5
+ $(element).children("h2, h3, h4, h5, h6").on("click", function() {
6
+ $(element).children(".section-data").toggleClass("display");
7
+ });
8
+ });
9
+ });
@@ -0,0 +1,53 @@
1
+ Productions:
2
+ %len = grammar.all_productions.size.to_s.size
3
+ %productions = grammar.all_productions.
4
+ % map { |x| ["#{x.label} → #{x.items.join(' ')}", x.block] }
5
+ %body = productions.map { |_| _.first.size }.max
6
+ %productions.each_with_index do |prod, i|
7
+ {{= sprintf("%#{len}s", i)}} {{= sprintf("%-#{body}s", prod[0])}} %{prod[1]}
8
+ %end
9
+
10
+ %if unused_symbols.any?
11
+ Symbols unused in grammar:
12
+ % unused_symbols.each do |sym|
13
+ %{sym}
14
+ % end
15
+ %end
16
+
17
+ Precedence:
18
+ --- highest
19
+ % grammar.precedence.each do |pr|
20
+ %{"%-8s" % pr.type} %{pr.level}:
21
+ {{= "{" << pr.tokens.to_a.join(", ") << "}" }}
22
+ % end
23
+ --- lowest
24
+
25
+ %states = grammar.states.to_a
26
+ %table.each_with_index do |v, i|
27
+ % state = states[i]
28
+ State %{i}:
29
+ % state.rules.each do |rule|
30
+ %{rule}
31
+ {%{rule.lookahead.to_a.join(", ")}}
32
+ % end
33
+ % transitions = v.each.select { |_, a| a && a[0] == :state }
34
+ % reductions = v.each.select { |_, a| a && a[0] == :reduce}
35
+ % accepting = v.each.select { |_, a| a && a[0] == :accept}
36
+ % thing = [:transitions, :reductions, :accepting]
37
+ % num_type = {
38
+ % transitions: "State",
39
+ % reductions: "Rule",
40
+ % accepting: "Rule"
41
+ % }
42
+ % h = Hash[thing.zip([transitions, reductions, accepting])]
43
+ % h.each do |key, value|
44
+ % next unless value.any?
45
+ %{key}:
46
+ % value.each do |token, (_, name)|
47
+ % token_value = grammar.terminals.
48
+ % find { |_| _.name == token } || token
49
+ %{token_value}: %{num_type[key]} %{name}
50
+ % end
51
+ % end
52
+
53
+ %end
@@ -1,146 +1,178 @@
1
-
2
- # This file assumes that the output of the generator will be placed
3
- # within a module or a class. However, the module/class requires a
4
- # `type` method, which takes a terminal and gives its type, as a
5
- # symbol. These types should line up with the terminals that were
6
- # defined in the original grammar.
7
-
8
- # The actions to take during parsing. In every state, there are a
9
- # set of acceptable peek tokens; this table tells the parser what
10
- # to do on each acceptable peek token. The possible actions include
11
- # `:accept`, `:reduce`, and `:state`; `:accept` means to accept the
12
- # input and return the value of the pasing. `:reduce` means to
13
- # reduce the top of the stack into a given nonterminal. `:state`
14
- # means to transition to another state.
15
- #
16
- # @return [Array<Hash<(Symbol, Array<(Symbol, Numeric)>)>>]
17
- ACTION_TABLE = {{= generate_action_table }}.freeze
18
-
19
- # A list of all of the productions. Only includes the left-hand side,
20
- # the number of tokens on the right-hand side, and the block to call
21
- # on reduction.
22
- #
23
- # @return [Array<Array<(Symbol, Numeric, Proc)>>]
24
- PRODUCTIONS = {{= generate_productions_list }}.freeze
25
-
26
- # Runs the parser.
27
- #
28
- # @param input [Array<Object>] the input to run the parser over.
29
- # @return [Object] the result of the accept.
30
- def parse(input)
31
- stack = []
32
- stack.push([nil, 0])
33
- input = input.dup
34
- last = nil
35
-
36
- until stack.empty? do
37
- last = parse_action(stack, input)
38
- end
39
-
40
- last
41
-
42
- end
43
-
44
- # Actually performs the parsing action on the given stack on input.
45
- # If you want to implement a push parser, than messing with this
46
- # method is probably the way to go.
47
- #
48
- # @param stack [Array<Array<(Object, Numeric)>>] the stack of the
49
- # parser. The actual order of the stack is important.
50
- # @param input [Array<Object>] the input to run the parser over.
51
- # The elements of this may be passed to the `type` method.
52
- # @return [Object] the result of the last accepting reduction.
53
- def parse_action(stack, input)
54
- last = nil
55
- peek_token = if input.empty?
56
- :$end
57
- else
58
- type(input.first)
59
- end
60
-
61
- action = ACTION_TABLE[stack.last.last].fetch(peek_token) do
62
- ACTION_TABLE[stack.last.last].fetch(:$default)
63
- end
64
- case action.first
65
- when :accept
66
- production = PRODUCTIONS[action.last]
67
- last = stack.pop(production[1]).first.first
68
- stack.pop
69
- when :reduce
70
- production = PRODUCTIONS[action.last]
71
- removing = stack.pop(production[1])
72
- value = instance_exec(*removing.map(&:first), &production[2])
73
- goto = ACTION_TABLE[stack.last.last][production[0]]
74
- stack.push([value, goto.last])
75
- when :state
76
- stack.push([input.shift, action.last])
77
- else
78
- raise NotImplementedError, "Unknown action #{action.first}"
79
- end
80
-
81
- last
82
-
83
- rescue KeyError => e
84
- if handle_error(
85
- { :stack => stack,
86
- :peek => peek_token,
87
- :remaining => input,
88
- :error => e,
89
- :expected => ACTION_TABLE[stack.last.last].keys
90
- })
91
- retry
92
- end
93
- end
94
-
95
- {{ if define_own_handler? }}
96
- def handle_error(data, _ = false)
97
- {{ if panic_mode? }}
98
- if _ || data[:peek] == :$end # we can't recover if
99
- # we're at the end
100
- {{ end }}
101
- raise {{= error_class }},
102
- "Unexpected token #{data[:peek]}; " \
103
- "expected one of #{data[:expected].join(', ')}",
104
- data[:error].backtrace
105
- {{ if panic_mode? }}
106
- end
107
-
108
- new_peek = :$error
109
- acceptable_state = false
110
- state = nil
111
-
112
- until data[:stack].empty? or acceptable_state
113
- state = data[:stack].last.last
114
-
115
- if ACTION_TABLE[state].key?(new_peek)
116
- acceptable_state = true
117
- else
118
- data[:stack].pop # discard
119
- end
120
- end
121
-
122
- return handle_error(data, true) unless acceptable_state
123
-
124
- action = ACTION_TABLE[state][new_peek]
125
- lookaheads = nil
126
-
127
- until lookaheads
128
- if action[0] == :state
129
- lookaheads = ACTION_TABLE[action.last].keys
130
- elsif action[0] == :reduce
131
- rule = PRODUCTIONS[action.last]
132
- action = ACTION_TABLE[stack[-rule[1]].last][rule[0]]
133
- end
134
- end
135
-
136
- until data[:remaining].empty? || lookaheads.
137
- include?(data[:remaining][0].first)
138
- data[:remaining].shift
139
- end
140
-
141
- data[:remaining].unshift([new_peek, data[:error]])
142
- true
143
-
144
- {{ end }}
145
- end
146
- {{ end }}
1
+
2
+ # This file assumes that the output of the generator will be placed
3
+ # within a module or a class. However, the module/class requires a
4
+ # `type` method, which takes a terminal and gives its type, as a
5
+ # symbol. These types should line up with the terminals that were
6
+ # defined in the original grammar.
7
+
8
+ # The actions to take during parsing. In every state, there are a
9
+ # set of acceptable peek tokens; this table tells the parser what
10
+ # to do on each acceptable peek token. The possible actions include
11
+ # `:accept`, `:reduce`, and `:state`; `:accept` means to accept the
12
+ # input and return the value of the pasing. `:reduce` means to
13
+ # reduce the top of the stack into a given nonterminal. `:state`
14
+ # means to transition to another state.
15
+ #
16
+ # @return [Array<Hash<(Symbol, Array<(Symbol, Numeric)>)>>]
17
+ ACTION_TABLE = {{= generate_action_table }}.freeze
18
+
19
+ # The default action that is taken for most reductions.
20
+ #
21
+ # @return [Proc]
22
+ DEFAULT_PROC = proc { |_| _ }
23
+ # A list of all of the productions. Only includes the left-hand side,
24
+ # the number of tokens on the right-hand side, and the block to call
25
+ # on reduction.
26
+ #
27
+ # @return [Array<Array<(Symbol, Numeric, Proc)>>]
28
+ PRODUCTIONS = {{= generate_productions_list }}.freeze
29
+
30
+ # Runs the parser.
31
+ #
32
+ # @param input [Array] the input to run the parser over.
33
+ # @return [Object] the result of the accept.
34
+ def parse(input)
35
+ stack = []
36
+ stack.push([nil, 0])
37
+ last = nil
38
+ input = input.to_a.dup
39
+
40
+ until stack.empty? do
41
+ last = parse_action(stack, input)
42
+ end
43
+
44
+ last
45
+
46
+ end
47
+
48
+ # Actually performs the parsing action on the given stack on input.
49
+ # If you want to implement a push parser, than messing with this
50
+ # method is probably the way to go.
51
+ #
52
+ # @param stack [Array<Array<(Object, Numeric)>>] the stack of the
53
+ # parser. The actual order of the stack is important.
54
+ # @param input [Array<Object>] the input to run the parser over.
55
+ # The elements of this may be passed to the `type` method.
56
+ # @return [Object] the result of the last accepting reduction.
57
+ def parse_action(stack, input)
58
+ last = nil
59
+ peek_token = if input.empty?
60
+ :$end
61
+ else
62
+ type(input.first)
63
+ end
64
+
65
+ action = ACTION_TABLE[stack.last.last].fetch(peek_token) do
66
+ ACTION_TABLE[stack.last.last].fetch(:$default)
67
+ end
68
+
69
+ case action.first
70
+ when :accept
71
+ production = PRODUCTIONS[action.last]
72
+ last = stack.pop(production[1]).first.first
73
+ stack.pop
74
+ when :reduce
75
+ production = PRODUCTIONS[action.last]
76
+ removing = stack.pop(production[1])
77
+ value = instance_exec(*removing.map(&:first), &production[2])
78
+ goto = ACTION_TABLE[stack.last.last][production[0]]
79
+ stack.push([value, goto.last])
80
+ when :state
81
+ stack.push([input.shift, action.last])
82
+ else
83
+ raise NotImplementedError, "Unknown action #{action.first}"
84
+ end
85
+
86
+ last
87
+
88
+ rescue KeyError => e
89
+ peek = input.first
90
+
91
+ if handle_error({
92
+ :stack => stack,
93
+ :peek => peek_token,
94
+ :remaining => input,
95
+ :error => e,
96
+ :line => line_of(peek),
97
+ :column => column_of(peek),
98
+ :expected => ACTION_TABLE[stack.last.last].keys
99
+ })
100
+ retry
101
+ else
102
+ raise
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def line_of(peek)
109
+ if peek.respond_to?(:line)
110
+ peek.line
111
+ else
112
+ 0
113
+ end
114
+ end
115
+
116
+ def column_of(peek)
117
+ if peek.respond_to?(:column)
118
+ peek.column
119
+ else
120
+ 0
121
+ end
122
+ end
123
+
124
+ {{ if define_own_handler? }}
125
+ def handle_error(data, _ = false)
126
+ {{ if panic_mode? }}
127
+ if _ || data[:peek] == :$end # we can't recover if
128
+ # we're at the end
129
+ {{ end }}
130
+ raise {{= error_class }},
131
+ "Unexpected token #{data[:peek]} on line #{data[:line]}, " \
132
+ "column #{data[:column]}; expected one of " \
133
+ "#{data[:expected].join(', ')}",
134
+ data[:error].backtrace
135
+ {{ if panic_mode? }}
136
+ end
137
+
138
+ new_peek = :$error
139
+ acceptable_state = false
140
+ state = nil
141
+
142
+ until data[:stack].empty? or acceptable_state
143
+ state = data[:stack].last.last
144
+
145
+ if ACTION_TABLE[state].key?(new_peek)
146
+ acceptable_state = true
147
+ else
148
+ data[:stack].pop # discard
149
+ end
150
+ end
151
+
152
+ return handle_error(data, true) unless acceptable_state
153
+
154
+ action = ACTION_TABLE[state][new_peek]
155
+ lookaheads = nil
156
+
157
+ until lookaheads
158
+ if action[0] == :state
159
+ lookaheads = ACTION_TABLE[action.last].keys
160
+ elsif action[0] == :reduce
161
+ rule = PRODUCTIONS[action.last]
162
+ action = ACTION_TABLE[stack[-rule[1]].last][rule[0]]
163
+ end
164
+ end
165
+
166
+ begin
167
+ until lookaheads.include?(data[:remaining][0].peek)
168
+ data[:remaining].next
169
+ end
170
+ rescue StopIteration
171
+ end
172
+
173
+ data[:remaining].unshift([new_peek, data[:error]])
174
+ true
175
+
176
+ {{ end }}
177
+ end
178
+ {{ end }}
@@ -1,63 +1,66 @@
1
- # encoding: utf-8
2
- require "erb"
3
- require "pathname"
4
-
5
- module Antelope
6
-
7
- # Contains the classes that generate parsers. This contains a
8
- # registery of all of the generators available to antelope.
9
- module Generator
10
-
11
- # Returns a hash of all of the generators registered within this
12
- # module. If a generator is accessed that does not exist on the
13
- # hash, it by default returns the {Generator::Null} class.
14
- #
15
- # @return [Hash<(Symbol, String) => Generator::Base>]
16
- def generators
17
- @_generators ||= Hash.new { |h, k| h[k] = Generator::Null }
18
- end
19
- # Returns a hash of all of the directives that are available in
20
- # the generators of this module.
21
- #
22
- # @see .generators
23
- # @return [Hash]
24
- def directives
25
- generators.values.map(&:directives).
26
- inject({}, :merge)
27
- end
28
-
29
- # Registers a generator with the given names. If multiple names
30
- # are given, they are assigned the generator as a value in the
31
- # {#generators} hash; otherwise, the one name is assigned the
32
- # generator as a value.
33
- #
34
- # @param generator [Generator::Base] the generator class to
35
- # associate the key with.
36
- # @param name [String, Symbol] a name to associate the generator
37
- # with.
38
- def register_generator(generator, *names)
39
- names = [names].flatten
40
- raise ArgumentError,
41
- "Requires at least one name" unless names.any?
42
- raise ArgumentError,
43
- "All name values must be a Symbol or string" unless names.
44
- all? {|_| [Symbol, String].include?(_.class) }
45
-
46
- names.each do |name|
47
- generators[name.to_s.downcase] = generator
48
- end
49
- end
50
-
51
- extend self
52
-
53
- end
54
- end
55
-
56
- require "antelope/generator/base"
57
- require "antelope/generator/group"
58
- require "antelope/generator/output"
59
- require "antelope/generator/ruby"
60
- require "antelope/generator/null"
61
- require "antelope/generator/c_header"
62
- require "antelope/generator/c_source"
63
- require "antelope/generator/c"
1
+ # encoding: utf-8
2
+ require "erb"
3
+ require "pathname"
4
+
5
+ module Antelope
6
+
7
+ # Contains the classes that generate parsers. This contains a
8
+ # registery of all of the generators available to antelope.
9
+ module Generator
10
+
11
+ # Returns a hash of all of the generators registered within this
12
+ # module. If a generator is accessed that does not exist on the
13
+ # hash, it by default returns the {Generator::Null} class.
14
+ #
15
+ # @return [Hash<(Symbol, String) => Generator::Base>]
16
+ def generators
17
+ @_generators ||= Hash.new { |h, k| h[k] = Generator::Null }
18
+ end
19
+ # Returns a hash of all of the directives that are available in
20
+ # the generators of this module.
21
+ #
22
+ # @see .generators
23
+ # @return [Hash]
24
+ def directives
25
+ generators.values.map(&:directives).
26
+ inject({}, :merge)
27
+ end
28
+
29
+ # Registers a generator with the given names. If multiple names
30
+ # are given, they are assigned the generator as a value in the
31
+ # {#generators} hash; otherwise, the one name is assigned the
32
+ # generator as a value.
33
+ #
34
+ # @param generator [Generator::Base] the generator class to
35
+ # associate the key with.
36
+ # @param name [String, Symbol] a name to associate the generator
37
+ # with.
38
+ def register_generator(generator, *names)
39
+ names = [names].flatten
40
+ raise ArgumentError,
41
+ "Requires at least one name" unless names.any?
42
+ raise ArgumentError,
43
+ "All name values must be a Symbol or string" unless names.
44
+ all? {|_| [Symbol, String].include?(_.class) }
45
+
46
+ names.each do |name|
47
+ generators[name.to_s.downcase] = generator
48
+ end
49
+ end
50
+
51
+ extend self
52
+
53
+ end
54
+ end
55
+
56
+ require "antelope/generator/base"
57
+ require "antelope/generator/group"
58
+ require "antelope/generator/info"
59
+ require "antelope/generator/error"
60
+ require "antelope/generator/output"
61
+ require "antelope/generator/html"
62
+ require "antelope/generator/ruby"
63
+ require "antelope/generator/null"
64
+ require "antelope/generator/c_header"
65
+ require "antelope/generator/c_source"
66
+ require "antelope/generator/c"