antelope 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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"