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.
- checksums.yaml +4 -4
- data/.gitignore +25 -23
- data/.rspec +3 -3
- data/.travis.yml +10 -9
- data/.yardopts +7 -7
- data/CONTRIBUTING.md +38 -38
- data/GENERATORS.md +124 -124
- data/Gemfile +7 -7
- data/LICENSE.txt +22 -22
- data/README.md +104 -104
- data/Rakefile +2 -2
- data/TODO.md +58 -58
- data/antelope.gemspec +28 -28
- data/bin/antelope +7 -7
- data/examples/deterministic.ace +35 -35
- data/examples/example.ace +51 -50
- data/examples/example.err +192 -0
- data/examples/{example.output → example.inf} +384 -385
- data/examples/liquidscript.ace +233 -162
- data/examples/simple.ace +22 -22
- data/lib/antelope/ace/compiler.rb +334 -334
- data/lib/antelope/ace/errors.rb +48 -48
- data/lib/antelope/ace/grammar/generation.rb +80 -80
- data/lib/antelope/ace/grammar/loading.rb +53 -53
- data/lib/antelope/ace/grammar/precedences.rb +68 -65
- data/lib/antelope/ace/grammar/productions.rb +156 -150
- data/lib/antelope/ace/grammar/symbols.rb +66 -66
- data/lib/antelope/ace/grammar.rb +69 -69
- data/lib/antelope/ace/precedence.rb +61 -61
- data/lib/antelope/ace/production.rb +57 -57
- data/lib/antelope/ace/scanner/argument.rb +57 -57
- data/lib/antelope/ace/scanner/first.rb +89 -89
- data/lib/antelope/ace/scanner/second.rb +177 -177
- data/lib/antelope/ace/scanner/third.rb +27 -27
- data/lib/antelope/ace/scanner.rb +134 -134
- data/lib/antelope/ace/token/epsilon.rb +24 -24
- data/lib/antelope/ace/token/error.rb +26 -26
- data/lib/antelope/ace/token/nonterminal.rb +17 -17
- data/lib/antelope/ace/token/terminal.rb +17 -17
- data/lib/antelope/ace/token.rb +238 -238
- data/lib/antelope/ace.rb +53 -53
- data/lib/antelope/cli.rb +55 -55
- data/lib/antelope/errors.rb +8 -8
- data/lib/antelope/generation/constructor/first.rb +88 -88
- data/lib/antelope/generation/constructor/follow.rb +103 -103
- data/lib/antelope/generation/constructor/nullable.rb +64 -64
- data/lib/antelope/generation/constructor.rb +126 -126
- data/lib/antelope/generation/errors.rb +17 -17
- data/lib/antelope/generation/null.rb +13 -13
- data/lib/antelope/generation/recognizer/rule.rb +216 -216
- data/lib/antelope/generation/recognizer/state.rb +130 -130
- data/lib/antelope/generation/recognizer.rb +180 -180
- data/lib/antelope/generation/tableizer.rb +175 -154
- data/lib/antelope/generation.rb +15 -15
- data/lib/antelope/generator/base.rb +264 -264
- data/lib/antelope/generator/c.rb +11 -11
- data/lib/antelope/generator/c_header.rb +105 -105
- data/lib/antelope/generator/c_source.rb +39 -39
- data/lib/antelope/generator/error.rb +34 -0
- data/lib/antelope/generator/group.rb +57 -57
- data/lib/antelope/generator/html.rb +51 -0
- data/lib/antelope/generator/info.rb +47 -0
- data/lib/antelope/generator/null.rb +18 -18
- data/lib/antelope/generator/output.rb +17 -49
- data/lib/antelope/generator/ruby.rb +79 -79
- data/lib/antelope/generator/templates/c_header.ant +36 -36
- data/lib/antelope/generator/templates/c_source.ant +202 -202
- data/lib/antelope/generator/templates/error.ant +33 -0
- data/lib/antelope/generator/templates/html/antelope.css +1 -0
- data/lib/antelope/generator/templates/html/antelope.html +1 -0
- data/lib/antelope/generator/templates/html/antelope.js +1 -0
- data/lib/antelope/generator/templates/html/css.ant +53 -0
- data/lib/antelope/generator/templates/html/html.ant +82 -0
- data/lib/antelope/generator/templates/html/js.ant +9 -0
- data/lib/antelope/generator/templates/info.ant +53 -0
- data/lib/antelope/generator/templates/ruby.ant +178 -146
- data/lib/antelope/generator.rb +66 -63
- data/lib/antelope/template/compiler.rb +78 -78
- data/lib/antelope/template/errors.rb +9 -9
- data/lib/antelope/template/scanner.rb +109 -109
- data/lib/antelope/template.rb +65 -60
- data/lib/antelope/version.rb +6 -6
- data/lib/antelope.rb +13 -13
- data/optimizations.txt +42 -0
- data/spec/antelope/ace/compiler_spec.rb +60 -60
- data/spec/antelope/ace/scanner_spec.rb +27 -27
- data/spec/antelope/constructor_spec.rb +133 -136
- data/spec/antelope/template_spec.rb +50 -49
- data/spec/fixtures/simple.ace +22 -22
- data/spec/spec_helper.rb +39 -39
- data/spec/support/benchmark_helper.rb +5 -5
- data/spec/support/grammar_helper.rb +15 -15
- data/subl/Ace (Ruby).JSON-tmLanguage +94 -94
- data/subl/Ace (Ruby).tmLanguage +153 -153
- metadata +17 -6
- data/lib/antelope/generator/templates/output.ant +0 -68
@@ -1,150 +1,156 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Antelope
|
4
|
-
module Ace
|
5
|
-
class Grammar
|
6
|
-
|
7
|
-
# Manages the productions of the grammar.
|
8
|
-
module Productions
|
9
|
-
|
10
|
-
# Returns a hash of all of the productions. The result is
|
11
|
-
# cached.
|
12
|
-
#
|
13
|
-
# @return [Hash<(Symbol, Array<Production>)>]
|
14
|
-
def productions
|
15
|
-
@_productions || generate_productions
|
16
|
-
end
|
17
|
-
|
18
|
-
# Returns all productions for all nonterminals, sorted by id.
|
19
|
-
#
|
20
|
-
# @return [Array<Production>]
|
21
|
-
def all_productions
|
22
|
-
productions.values.flatten.sort_by(&:id)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Finds a token based on its corresponding symbol. First
|
26
|
-
# checks the productions, to see if it's a nonterminal; then,
|
27
|
-
# tries to find it in the terminals; otherwise, if the symbol
|
28
|
-
# is `error`, it returns a {Token::Error}; if the symbol is
|
29
|
-
# `nothing` or `ε`, it returns a {Token::Epsilon}; if it's
|
30
|
-
# none of those, it raises an {UndefinedTokenError}.
|
31
|
-
#
|
32
|
-
# @raise [UndefinedTokenError] if the token doesn't exist.
|
33
|
-
# @param value [String, Symbol, #intern] the token's symbol to
|
34
|
-
# check.
|
35
|
-
# @return [Token]
|
36
|
-
def find_token(value)
|
37
|
-
value = value.intern
|
38
|
-
|
39
|
-
if productions.key?(value)
|
40
|
-
typed_nonterminals.find { |term| term.name == value } ||
|
41
|
-
Token::Nonterminal.new(value)
|
42
|
-
elsif terminal = terminals.
|
43
|
-
find { |term| term.name == value }
|
44
|
-
terminal
|
45
|
-
elsif value == :error
|
46
|
-
Token::Error.new
|
47
|
-
elsif [:nothing,
|
48
|
-
Token::Epsilon.new
|
49
|
-
else
|
50
|
-
raise UndefinedTokenError, "Could not find a token " \
|
51
|
-
"named #{value.inspect}"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
# Actually generates the productions. Uses the rules from the
|
58
|
-
# compiler to construct the productions. Makes two loops over
|
59
|
-
# the compiler's rules; the first to tell the grammar that the
|
60
|
-
# nonterminal does exist, and the second to actually construct
|
61
|
-
# the productions. The first loop is for {#find_token},
|
62
|
-
# because otherwise it wouldn't be able to return a
|
63
|
-
# nonterminal properly.
|
64
|
-
#
|
65
|
-
# @return [Hash<(Symbol, Array<Production>)>]
|
66
|
-
def generate_productions
|
67
|
-
@_productions = {}
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
when Token::
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
#
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Antelope
|
4
|
+
module Ace
|
5
|
+
class Grammar
|
6
|
+
|
7
|
+
# Manages the productions of the grammar.
|
8
|
+
module Productions
|
9
|
+
|
10
|
+
# Returns a hash of all of the productions. The result is
|
11
|
+
# cached.
|
12
|
+
#
|
13
|
+
# @return [Hash<(Symbol, Array<Production>)>]
|
14
|
+
def productions
|
15
|
+
@_productions || generate_productions
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns all productions for all nonterminals, sorted by id.
|
19
|
+
#
|
20
|
+
# @return [Array<Production>]
|
21
|
+
def all_productions
|
22
|
+
productions.values.flatten.sort_by(&:id)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Finds a token based on its corresponding symbol. First
|
26
|
+
# checks the productions, to see if it's a nonterminal; then,
|
27
|
+
# tries to find it in the terminals; otherwise, if the symbol
|
28
|
+
# is `error`, it returns a {Token::Error}; if the symbol is
|
29
|
+
# `nothing` or `ε`, it returns a {Token::Epsilon}; if it's
|
30
|
+
# none of those, it raises an {UndefinedTokenError}.
|
31
|
+
#
|
32
|
+
# @raise [UndefinedTokenError] if the token doesn't exist.
|
33
|
+
# @param value [String, Symbol, #intern] the token's symbol to
|
34
|
+
# check.
|
35
|
+
# @return [Token]
|
36
|
+
def find_token(value)
|
37
|
+
value = value.intern
|
38
|
+
|
39
|
+
if productions.key?(value)
|
40
|
+
typed_nonterminals.find { |term| term.name == value } ||
|
41
|
+
Token::Nonterminal.new(value)
|
42
|
+
elsif terminal = terminals.
|
43
|
+
find { |term| term.name == value }
|
44
|
+
terminal
|
45
|
+
elsif value == :error
|
46
|
+
Token::Error.new
|
47
|
+
elsif [:nothing, :ε, :"%empty"].include?(value)
|
48
|
+
Token::Epsilon.new
|
49
|
+
else
|
50
|
+
raise UndefinedTokenError, "Could not find a token " \
|
51
|
+
"named #{value.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Actually generates the productions. Uses the rules from the
|
58
|
+
# compiler to construct the productions. Makes two loops over
|
59
|
+
# the compiler's rules; the first to tell the grammar that the
|
60
|
+
# nonterminal does exist, and the second to actually construct
|
61
|
+
# the productions. The first loop is for {#find_token},
|
62
|
+
# because otherwise it wouldn't be able to return a
|
63
|
+
# nonterminal properly.
|
64
|
+
#
|
65
|
+
# @return [Hash<(Symbol, Array<Production>)>]
|
66
|
+
def generate_productions
|
67
|
+
@_productions = {}
|
68
|
+
index = 0
|
69
|
+
|
70
|
+
rules = @compiler.rules.each do |rule|
|
71
|
+
productions[rule[:label]] = []
|
72
|
+
end
|
73
|
+
|
74
|
+
while index < rules.size
|
75
|
+
rule = rules[index]
|
76
|
+
productions[rule[:label]] <<
|
77
|
+
generate_production_for(rule, index)
|
78
|
+
index += 1
|
79
|
+
end
|
80
|
+
|
81
|
+
productions[:$start] = [default_production]
|
82
|
+
|
83
|
+
productions
|
84
|
+
end
|
85
|
+
|
86
|
+
# Generates a production for a given compiler rule. Converts
|
87
|
+
# the tokens in the set to their {Token} counterparts,
|
88
|
+
# and then sets the precedence for the production. If the
|
89
|
+
# precedence declaration from the compiler rule is empty,
|
90
|
+
# then it'll use the last terminal from the set to check for
|
91
|
+
# precedence; otherwise, it'll use the precedence declaration.
|
92
|
+
# This is to make sure that every production has a precedence
|
93
|
+
# declaration.
|
94
|
+
#
|
95
|
+
# @param rule [Hash] the compiler's rule.
|
96
|
+
# @param id [Numeric] the id for the production.
|
97
|
+
# @return [Production]
|
98
|
+
def generate_production_for(rule, id)
|
99
|
+
left = Token::Nonterminal.new(rule[:label])
|
100
|
+
items = rule[:set].map { |_| find_token(_[0]) }
|
101
|
+
prec = if rule[:prec].empty?
|
102
|
+
items.select(&:terminal?).last
|
103
|
+
else
|
104
|
+
rule[:prec].intern
|
105
|
+
end
|
106
|
+
|
107
|
+
prec = precedence_for(prec)
|
108
|
+
left.type = type_for(rule[:label])
|
109
|
+
left.id = rule[:label_id]
|
110
|
+
|
111
|
+
rule[:set].each_with_index do |tok, i|
|
112
|
+
items[i] = items[i].dup
|
113
|
+
items[i].id = tok[1]
|
114
|
+
end
|
115
|
+
items.delete_if(&:epsilon?)
|
116
|
+
|
117
|
+
Production.new(left, items, rule[:block], prec, id + 1)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns the defined type for the given token name.
|
121
|
+
# Uses the `%type` directive to infer the corresponding types.
|
122
|
+
#
|
123
|
+
# @param token [Symbol] the token to check for
|
124
|
+
# types.
|
125
|
+
def type_for(token)
|
126
|
+
token = find_token(token) unless token.is_a?(Token)
|
127
|
+
|
128
|
+
case token
|
129
|
+
when Token::Nonterminal
|
130
|
+
token.type
|
131
|
+
when Token::Terminal
|
132
|
+
token.type
|
133
|
+
when Token::Epsilon
|
134
|
+
""
|
135
|
+
when Token::Error
|
136
|
+
""
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Creates the default production for the grammar. The left
|
141
|
+
# hand side of the production is the `:$start` symbol, with
|
142
|
+
# the right hand side being the first rule's left-hand side
|
143
|
+
# and the terminal `$`. This production is automagically
|
144
|
+
# given the last precedence, and an id of 0.
|
145
|
+
#
|
146
|
+
# @return [Production]
|
147
|
+
def default_production
|
148
|
+
Production.new(Token::Nonterminal.new(:$start), [
|
149
|
+
Token::Nonterminal.new(@compiler.rules.first[:label]),
|
150
|
+
Token::Terminal.new(:$end)
|
151
|
+
], "", precedence.last, 0)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -1,66 +1,66 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Antelope
|
4
|
-
module Ace
|
5
|
-
class Grammar
|
6
|
-
|
7
|
-
# Manages a list of the symbols in the grammar.
|
8
|
-
module Symbols
|
9
|
-
|
10
|
-
# A list of all terminals in the grammar. Checks the compiler
|
11
|
-
# options for terminals, and then returns an array of
|
12
|
-
# terminals. Caches the result.
|
13
|
-
#
|
14
|
-
# @return [Array<Token::Terminal>]
|
15
|
-
def terminals
|
16
|
-
@_terminals ||= begin
|
17
|
-
@compiler.options.fetch(:terminals
|
18
|
-
Token::Terminal.new(*v)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# A list of all nonterminals in the grammar.
|
24
|
-
#
|
25
|
-
# @return [Array<Symbol>]
|
26
|
-
# @see #productions
|
27
|
-
def nonterminals
|
28
|
-
@_nonterminals ||= productions.keys
|
29
|
-
end
|
30
|
-
|
31
|
-
# A list of all nonterminals, with types.
|
32
|
-
#
|
33
|
-
# @return [Array<Token::Nonterminal>>]
|
34
|
-
def typed_nonterminals
|
35
|
-
@_typed_nonterminals ||= begin
|
36
|
-
typed = []
|
37
|
-
compiler.options[:nonterminals].each do |data|
|
38
|
-
data[1].each do |nonterm|
|
39
|
-
typed << Token::Nonterminal.new(nonterm, data[0])
|
40
|
-
end
|
41
|
-
end
|
42
|
-
typed
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# A list of all symbols in the grammar; includes both
|
47
|
-
# terminals and nonterminals.
|
48
|
-
#
|
49
|
-
# @return [Array<Token::Terminal, Symbol>]
|
50
|
-
# @see #terminals
|
51
|
-
# @see #nonterminals
|
52
|
-
def symbols
|
53
|
-
@_symbols ||= terminals + nonterminals
|
54
|
-
end
|
55
|
-
|
56
|
-
# Checks to see if the grammar uses the `error` terminal
|
57
|
-
# anywhere.
|
58
|
-
#
|
59
|
-
# @return [Boolean]
|
60
|
-
def contains_error_token?
|
61
|
-
all_productions.any? { |_| _.items.any?(&:error?) }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Antelope
|
4
|
+
module Ace
|
5
|
+
class Grammar
|
6
|
+
|
7
|
+
# Manages a list of the symbols in the grammar.
|
8
|
+
module Symbols
|
9
|
+
|
10
|
+
# A list of all terminals in the grammar. Checks the compiler
|
11
|
+
# options for terminals, and then returns an array of
|
12
|
+
# terminals. Caches the result.
|
13
|
+
#
|
14
|
+
# @return [Array<Token::Terminal>]
|
15
|
+
def terminals
|
16
|
+
@_terminals ||= begin
|
17
|
+
@compiler.options.fetch(:terminals) { [] }.map do |v|
|
18
|
+
Token::Terminal.new(*v)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# A list of all nonterminals in the grammar.
|
24
|
+
#
|
25
|
+
# @return [Array<Symbol>]
|
26
|
+
# @see #productions
|
27
|
+
def nonterminals
|
28
|
+
@_nonterminals ||= productions.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
# A list of all nonterminals, with types.
|
32
|
+
#
|
33
|
+
# @return [Array<Token::Nonterminal>>]
|
34
|
+
def typed_nonterminals
|
35
|
+
@_typed_nonterminals ||= begin
|
36
|
+
typed = []
|
37
|
+
compiler.options[:nonterminals].each do |data|
|
38
|
+
data[1].each do |nonterm|
|
39
|
+
typed << Token::Nonterminal.new(nonterm, data[0])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
typed
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# A list of all symbols in the grammar; includes both
|
47
|
+
# terminals and nonterminals.
|
48
|
+
#
|
49
|
+
# @return [Array<Token::Terminal, Symbol>]
|
50
|
+
# @see #terminals
|
51
|
+
# @see #nonterminals
|
52
|
+
def symbols
|
53
|
+
@_symbols ||= terminals + nonterminals
|
54
|
+
end
|
55
|
+
|
56
|
+
# Checks to see if the grammar uses the `error` terminal
|
57
|
+
# anywhere.
|
58
|
+
#
|
59
|
+
# @return [Boolean]
|
60
|
+
def contains_error_token?
|
61
|
+
all_productions.any? { |_| _.items.any?(&:error?) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/antelope/ace/grammar.rb
CHANGED
@@ -1,69 +1,69 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "hashie"
|
4
|
-
require "antelope/ace/grammar/symbols"
|
5
|
-
require "antelope/ace/grammar/productions"
|
6
|
-
require "antelope/ace/grammar/precedences"
|
7
|
-
require "antelope/ace/grammar/loading"
|
8
|
-
require "antelope/ace/grammar/generation"
|
9
|
-
|
10
|
-
module Antelope
|
11
|
-
module Ace
|
12
|
-
|
13
|
-
# Defines a grammar from an Ace file. This handles setting up
|
14
|
-
# productions, loading from files, symbols, precedence, and
|
15
|
-
# generation.
|
16
|
-
class Grammar
|
17
|
-
|
18
|
-
include Symbols
|
19
|
-
include Productions
|
20
|
-
include Precedences
|
21
|
-
include Loading
|
22
|
-
include Grammar::Generation
|
23
|
-
|
24
|
-
# Used by a generation class; this is all the generated states
|
25
|
-
# of the grammar.
|
26
|
-
#
|
27
|
-
# @return [Set<Generation::Recognizer::State>]
|
28
|
-
# @see Generation::Recognizer
|
29
|
-
attr_accessor :states
|
30
|
-
|
31
|
-
# The name of the grammar. This is normally assumed from a file
|
32
|
-
# name.
|
33
|
-
#
|
34
|
-
# @return [String]
|
35
|
-
attr_accessor :name
|
36
|
-
|
37
|
-
# The output directory for the grammar. This is normally the
|
38
|
-
# same directory as the Ace file.
|
39
|
-
#
|
40
|
-
# @return [Pathname]
|
41
|
-
attr_accessor :output
|
42
|
-
|
43
|
-
# The compiler for the Ace file.
|
44
|
-
#
|
45
|
-
# @return [Compiler]
|
46
|
-
attr_reader :compiler
|
47
|
-
|
48
|
-
# Initialize.
|
49
|
-
#
|
50
|
-
# @param name [String]
|
51
|
-
# @param output [String] the output directory. Automagically
|
52
|
-
# turned into a Pathname.
|
53
|
-
# @param compiler [Compiler]
|
54
|
-
def initialize(name, output, compiler)
|
55
|
-
@name = name
|
56
|
-
@output = Pathname.new(output)
|
57
|
-
@compiler = compiler
|
58
|
-
end
|
59
|
-
|
60
|
-
# Extra options from the compiler. This can be used by
|
61
|
-
# generators for output information.
|
62
|
-
#
|
63
|
-
# @return [Hash]
|
64
|
-
def options
|
65
|
-
compiler.options[:extra]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "hashie"
|
4
|
+
require "antelope/ace/grammar/symbols"
|
5
|
+
require "antelope/ace/grammar/productions"
|
6
|
+
require "antelope/ace/grammar/precedences"
|
7
|
+
require "antelope/ace/grammar/loading"
|
8
|
+
require "antelope/ace/grammar/generation"
|
9
|
+
|
10
|
+
module Antelope
|
11
|
+
module Ace
|
12
|
+
|
13
|
+
# Defines a grammar from an Ace file. This handles setting up
|
14
|
+
# productions, loading from files, symbols, precedence, and
|
15
|
+
# generation.
|
16
|
+
class Grammar
|
17
|
+
|
18
|
+
include Symbols
|
19
|
+
include Productions
|
20
|
+
include Precedences
|
21
|
+
include Loading
|
22
|
+
include Grammar::Generation
|
23
|
+
|
24
|
+
# Used by a generation class; this is all the generated states
|
25
|
+
# of the grammar.
|
26
|
+
#
|
27
|
+
# @return [Set<Generation::Recognizer::State>]
|
28
|
+
# @see Generation::Recognizer
|
29
|
+
attr_accessor :states
|
30
|
+
|
31
|
+
# The name of the grammar. This is normally assumed from a file
|
32
|
+
# name.
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
attr_accessor :name
|
36
|
+
|
37
|
+
# The output directory for the grammar. This is normally the
|
38
|
+
# same directory as the Ace file.
|
39
|
+
#
|
40
|
+
# @return [Pathname]
|
41
|
+
attr_accessor :output
|
42
|
+
|
43
|
+
# The compiler for the Ace file.
|
44
|
+
#
|
45
|
+
# @return [Compiler]
|
46
|
+
attr_reader :compiler
|
47
|
+
|
48
|
+
# Initialize.
|
49
|
+
#
|
50
|
+
# @param name [String]
|
51
|
+
# @param output [String] the output directory. Automagically
|
52
|
+
# turned into a Pathname.
|
53
|
+
# @param compiler [Compiler]
|
54
|
+
def initialize(name, output, compiler)
|
55
|
+
@name = name
|
56
|
+
@output = Pathname.new(output)
|
57
|
+
@compiler = compiler
|
58
|
+
end
|
59
|
+
|
60
|
+
# Extra options from the compiler. This can be used by
|
61
|
+
# generators for output information.
|
62
|
+
#
|
63
|
+
# @return [Hash]
|
64
|
+
def options
|
65
|
+
compiler.options[:extra]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|