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