antelope 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/antelope.gemspec +0 -2
- data/bin/antelope +3 -20
- data/examples/deterministic.output +97 -103
- data/examples/example.ace +0 -1
- data/examples/example.output +259 -333
- data/examples/simple.output +85 -87
- data/lib/antelope/ace/compiler.rb +14 -16
- data/lib/antelope/ace/errors.rb +9 -3
- data/lib/antelope/ace/grammar/generation.rb +38 -7
- data/lib/antelope/ace/grammar/precedences.rb +59 -0
- data/lib/antelope/ace/grammar/production.rb +24 -25
- data/lib/antelope/ace/grammar/productions.rb +8 -8
- data/lib/antelope/ace/grammar.rb +3 -3
- data/lib/antelope/ace/{presidence.rb → precedence.rb} +11 -11
- data/lib/antelope/ace/scanner/second.rb +2 -2
- data/lib/antelope/ace/token.rb +1 -1
- data/lib/antelope/ace.rb +2 -2
- data/lib/antelope/cli.rb +33 -0
- data/lib/antelope/errors.rb +6 -0
- data/lib/antelope/generation/constructor/first.rb +40 -6
- data/lib/antelope/generation/constructor/follow.rb +83 -25
- data/lib/antelope/generation/constructor/nullable.rb +24 -2
- data/lib/antelope/generation/constructor.rb +39 -13
- data/lib/antelope/generation/errors.rb +15 -0
- data/lib/antelope/generation/recognizer/rule.rb +111 -11
- data/lib/antelope/generation/recognizer/state.rb +53 -5
- data/lib/antelope/generation/recognizer.rb +31 -1
- data/lib/antelope/generation/tableizer.rb +42 -10
- data/lib/antelope/generation.rb +1 -1
- data/lib/antelope/generator/templates/output.erb +19 -18
- data/lib/antelope/version.rb +1 -1
- data/lib/antelope.rb +3 -2
- metadata +7 -36
- data/lib/antelope/ace/grammar/presidence.rb +0 -59
- data/lib/antelope/automaton.rb +0 -36
- data/lib/antelope/generation/conflictor/conflict.rb +0 -7
- data/lib/antelope/generation/conflictor.rb +0 -45
- data/lib/antelope/generation/constructor/lookahead.rb +0 -42
data/examples/simple.output
CHANGED
@@ -1,30 +1,36 @@
|
|
1
1
|
Productions:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
e →
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
l → "*" r
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
2
|
+
e → l "=" r
|
3
|
+
e → r
|
4
|
+
l → IDENT
|
5
|
+
l → "*" r
|
6
|
+
r → l
|
7
|
+
$start → e $
|
8
|
+
|
9
|
+
Productions, Again:
|
10
|
+
0/n0: $start(0) → e(0:1) $
|
11
|
+
1/n1: e(0:1) → l(0:2) "=" r(8:10)
|
12
|
+
2/n1: e(0:1) → r(0:3)
|
13
|
+
3/n1: l(0:2) → IDENT
|
14
|
+
4/n1: l(0:2) → "*" r(5:9)
|
15
|
+
5/n1: r(0:3) → l(0:2)
|
16
|
+
12/n1: r(5:9) → l(5:2)
|
17
|
+
13/n1: l(5:2) → IDENT
|
18
|
+
14/n1: l(5:2) → "*" r(5:9)
|
19
|
+
18/n1: r(8:10) → l(8:2)
|
20
|
+
19/n1: l(8:2) → IDENT
|
21
|
+
20/n1: l(8:2) → "*" r(5:9)
|
22
|
+
|
23
|
+
FOLLOW:
|
24
|
+
$start(0): {}
|
25
|
+
e(0:1): {$}
|
26
|
+
l(0:2): {"=", $}
|
27
|
+
r(0:3): {$}
|
28
|
+
r(5:9): {"=", $}
|
29
|
+
l(5:2): {}
|
30
|
+
l(8:2): {$}
|
31
|
+
r(8:10): {$}
|
32
|
+
|
33
|
+
Precedence:
|
28
34
|
--- highest
|
29
35
|
nonassoc 1:
|
30
36
|
{_}
|
@@ -33,48 +39,40 @@ Presidence:
|
|
33
39
|
--- lowest
|
34
40
|
|
35
41
|
Table:
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
1
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
5
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
#<Antelope::Generation::Recognizer::Rule id=15 left=r(8:10) right=[l] position=1>,
|
71
|
-
#<Antelope::Generation::Recognizer::Rule id=16 left=$start(0) right=[e $] position=2>,
|
72
|
-
#<Antelope::Generation::Recognizer::Rule id=17 left=e(0:1) right=[l "=" r] position=2>,
|
73
|
-
#<Antelope::Generation::Recognizer::Rule id=18 left=r(8:10) right=[l(8:2)] position=0>,
|
74
|
-
#<Antelope::Generation::Recognizer::Rule id=19 left=l(8:2) right=[IDENT] position=0>,
|
75
|
-
#<Antelope::Generation::Recognizer::Rule id=20 left=l(8:2) right=["*" r(5:9)] position=0>,
|
76
|
-
#<Antelope::Generation::Recognizer::Rule id=21 left=l(8:2) right=["*" r] position=2>,
|
77
|
-
#<Antelope::Generation::Recognizer::Rule id=22 left=e(0:1) right=[l "=" r] position=3>]
|
42
|
+
State 0:
|
43
|
+
e : state (1)
|
44
|
+
l : state (2)
|
45
|
+
r : state (3)
|
46
|
+
IDENT : state (4)
|
47
|
+
STAR : state (5)
|
48
|
+
State 1:
|
49
|
+
$ : state (7)
|
50
|
+
State 2:
|
51
|
+
EQUALS: state (8)
|
52
|
+
$ : reduce (5)
|
53
|
+
State 3:
|
54
|
+
$ : reduce (2)
|
55
|
+
State 4:
|
56
|
+
$ : reduce (3)
|
57
|
+
State 5:
|
58
|
+
r : state (9)
|
59
|
+
l : state (2)
|
60
|
+
IDENT : state (4)
|
61
|
+
STAR : state (5)
|
62
|
+
State 6:
|
63
|
+
$ : reduce (5)
|
64
|
+
State 7:
|
65
|
+
$ : accept (0)
|
66
|
+
State 8:
|
67
|
+
r : state (10)
|
68
|
+
l : state (2)
|
69
|
+
IDENT : state (4)
|
70
|
+
STAR : state (5)
|
71
|
+
State 9:
|
72
|
+
$ : reduce (4)
|
73
|
+
State 10:
|
74
|
+
$ : reduce (1)
|
75
|
+
|
78
76
|
|
79
77
|
State 0:
|
80
78
|
rules:
|
@@ -84,11 +82,11 @@ State 0:
|
|
84
82
|
{}
|
85
83
|
2/n1: e(0:1) → • r(0:3)
|
86
84
|
{}
|
87
|
-
3/n1: l(
|
85
|
+
3/n1: l(0:2) → • IDENT
|
88
86
|
{}
|
89
|
-
4/n1: l(
|
87
|
+
4/n1: l(0:2) → • "*" r(5:9)
|
90
88
|
{}
|
91
|
-
5/n1: r(
|
89
|
+
5/n1: r(0:3) → • l(0:2)
|
92
90
|
{}
|
93
91
|
|
94
92
|
transitions:
|
@@ -100,7 +98,7 @@ State 0:
|
|
100
98
|
|
101
99
|
State 1:
|
102
100
|
rules:
|
103
|
-
6/n0: $start
|
101
|
+
6/n0: $start → e • $
|
104
102
|
{}
|
105
103
|
|
106
104
|
transitions:
|
@@ -108,9 +106,9 @@ State 1:
|
|
108
106
|
|
109
107
|
State 2:
|
110
108
|
rules:
|
111
|
-
7/n1: e
|
109
|
+
7/n1: e → l • "=" r
|
112
110
|
{}
|
113
|
-
15/n1: r
|
111
|
+
15/n1: r → l •
|
114
112
|
{$}
|
115
113
|
|
116
114
|
transitions:
|
@@ -118,27 +116,27 @@ State 2:
|
|
118
116
|
|
119
117
|
State 3:
|
120
118
|
rules:
|
121
|
-
9/n1: e
|
119
|
+
9/n1: e → r •
|
122
120
|
{$}
|
123
121
|
|
124
122
|
transitions:
|
125
123
|
|
126
124
|
State 4:
|
127
125
|
rules:
|
128
|
-
10/n1: l
|
129
|
-
{
|
126
|
+
10/n1: l → IDENT •
|
127
|
+
{$}
|
130
128
|
|
131
129
|
transitions:
|
132
130
|
|
133
131
|
State 5:
|
134
132
|
rules:
|
135
|
-
11/n1: l
|
133
|
+
11/n1: l → "*" • r
|
136
134
|
{}
|
137
|
-
12/n1: r(
|
135
|
+
12/n1: r(5:9) → • l(5:2)
|
138
136
|
{}
|
139
|
-
13/n1: l(
|
137
|
+
13/n1: l(5:2) → • IDENT
|
140
138
|
{}
|
141
|
-
14/n1: l(
|
139
|
+
14/n1: l(5:2) → • "*" r(5:9)
|
142
140
|
{}
|
143
141
|
|
144
142
|
transitions:
|
@@ -149,21 +147,21 @@ State 5:
|
|
149
147
|
|
150
148
|
State 6:
|
151
149
|
rules:
|
152
|
-
15/n1: r
|
150
|
+
15/n1: r → l •
|
153
151
|
{$}
|
154
152
|
|
155
153
|
transitions:
|
156
154
|
|
157
155
|
State 7:
|
158
156
|
rules:
|
159
|
-
16/n0: $start
|
157
|
+
16/n0: $start → e $ •
|
160
158
|
{}
|
161
159
|
|
162
160
|
transitions:
|
163
161
|
|
164
162
|
State 8:
|
165
163
|
rules:
|
166
|
-
17/n1: e
|
164
|
+
17/n1: e → l "=" • r
|
167
165
|
{}
|
168
166
|
18/n1: r(8:10) → • l(8:2)
|
169
167
|
{}
|
@@ -180,14 +178,14 @@ State 8:
|
|
180
178
|
|
181
179
|
State 9:
|
182
180
|
rules:
|
183
|
-
21/n1: l
|
184
|
-
{
|
181
|
+
21/n1: l → "*" r •
|
182
|
+
{$}
|
185
183
|
|
186
184
|
transitions:
|
187
185
|
|
188
186
|
State 10:
|
189
187
|
rules:
|
190
|
-
22/n1: e
|
188
|
+
22/n1: e → l "=" r •
|
191
189
|
{$}
|
192
190
|
|
193
191
|
transitions:
|
@@ -42,7 +42,7 @@ module Antelope
|
|
42
42
|
# - **`block`** (`String`) — The code to be run on a reduction.
|
43
43
|
# this should be formatted in the language that the output
|
44
44
|
# parser is written in. Optional; default value is `""`.
|
45
|
-
# - **`prec`** (`String`) — The
|
45
|
+
# - **`prec`** (`String`) — The precedence level for the
|
46
46
|
# rule. This should be a nonterminal or terminal. Optional;
|
47
47
|
# default value is `""`.
|
48
48
|
#
|
@@ -56,13 +56,12 @@ module Antelope
|
|
56
56
|
# properly defined, the grammar will throw an error saying
|
57
57
|
# that a symbol used in the grammar is not defined.
|
58
58
|
# - **`:prec`** (`Array<(Symbol, Array<Symbol>)>`) — A list
|
59
|
-
# of the
|
60
|
-
# of each element is the _type_ of
|
59
|
+
# of the precedence rules of the grammar. The first element
|
60
|
+
# of each element is the _type_ of precedence (and should be
|
61
61
|
# any of `:left`, `:right`, or `:nonassoc`), and the second
|
62
62
|
# element should be the symbols that are on that level.
|
63
63
|
# - **`:type`** (`String`) — The type of generator to
|
64
|
-
# generate; this should be a language.
|
65
|
-
# ineffective.
|
64
|
+
# generate; this should be a language.
|
66
65
|
# - **`:extra`** (`Hash<Symbol, Array<Object>>`) — Extra
|
67
66
|
# options that are not defined here.
|
68
67
|
# @return [Hash]
|
@@ -119,18 +118,17 @@ module Antelope
|
|
119
118
|
# Requires 1 argument. If the first argument is a version
|
120
119
|
# greater than the current version of Antelope, it raises
|
121
120
|
# an error.
|
122
|
-
# - `:left` — creates a new
|
123
|
-
# argument values being the symbols. The
|
121
|
+
# - `:left` — creates a new precedence level, with the
|
122
|
+
# argument values being the symbols. The precedence level
|
124
123
|
# is left associative.
|
125
|
-
# - `:right` — creates a new
|
126
|
-
# argument valeus being the symbols. The
|
124
|
+
# - `:right` — creates a new precedence level, with the
|
125
|
+
# argument valeus being the symbols. The precedence level
|
127
126
|
# is right associative.
|
128
|
-
# - `:nonassoc` — creates a nre
|
129
|
-
# argument values being the symbols. The
|
127
|
+
# - `:nonassoc` — creates a nre precedence level, with the
|
128
|
+
# argument values being the symbols. The precedence level
|
130
129
|
# is nonassociative.
|
131
130
|
# - `:type` — the type of parser to generate. This should
|
132
|
-
# correspond to the output language of the parser.
|
133
|
-
# ineffective.
|
131
|
+
# correspond to the output language of the parser.
|
134
132
|
#
|
135
133
|
# @param name [String, Symbol] the name of the directive.
|
136
134
|
# Accepts any of `:terminal`, `:require`, `:left`, `:right`,
|
@@ -221,11 +219,11 @@ module Antelope
|
|
221
219
|
compile_label(@current_label)
|
222
220
|
end
|
223
221
|
|
224
|
-
# Compiles the
|
222
|
+
# Compiles the precedence operator. This should only occur in a
|
225
223
|
# rule definition, and in the second part. It sets the
|
226
|
-
#
|
224
|
+
# precedence definition on the current rule.
|
227
225
|
#
|
228
|
-
# @param prec [String] the
|
226
|
+
# @param prec [String] the precedence of the rule.
|
229
227
|
# @return [void]
|
230
228
|
def compile_prec(prec)
|
231
229
|
require_state! :second
|
data/lib/antelope/ace/errors.rb
CHANGED
@@ -4,7 +4,7 @@ module Antelope
|
|
4
4
|
# Defines an error that can occur within the Ace module. All
|
5
5
|
# errors that are raised within the Ace module are subclasses of
|
6
6
|
# this.
|
7
|
-
class Error <
|
7
|
+
class Error < Antelope::Error
|
8
8
|
end
|
9
9
|
|
10
10
|
# Used primarily in the {Scanner}, this is raised when an input
|
@@ -19,9 +19,15 @@ module Antelope
|
|
19
19
|
class UndefinedTokenError < Error
|
20
20
|
end
|
21
21
|
|
22
|
-
#
|
23
|
-
# should not be in the current state, this is raised.
|
22
|
+
# Primarily used in the {Compiler}, if a scanner token appears
|
23
|
+
# that should not be in the current state, this is raised.
|
24
24
|
class InvalidStateError < Error
|
25
25
|
end
|
26
|
+
|
27
|
+
# Primarily used in the {Grammar} (specifically
|
28
|
+
# {Grammar::Generation}), if the grammar could not determine the
|
29
|
+
# generator to use for the generation, it raises this.
|
30
|
+
class NoTypeError < Error
|
31
|
+
end
|
26
32
|
end
|
27
33
|
end
|
@@ -8,14 +8,12 @@ module Antelope
|
|
8
8
|
DEFAULT_MODIFIERS = [
|
9
9
|
[:recognizer, Generation::Recognizer ],
|
10
10
|
[:constructor, Generation::Constructor],
|
11
|
-
[:conflictor, Generation::Conflictor ],
|
12
11
|
[:tableizer, Generation::Tableizer ]
|
13
12
|
].freeze
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
DEFAULT_GENERATORS = [Generator::Output, Generator::Ruby].freeze
|
14
|
+
DEFAULT_GENERATORS = {
|
15
|
+
"ruby" => [Generator::Ruby]
|
16
|
+
}
|
19
17
|
|
20
18
|
# Handles the generation of output for the grammar.
|
21
19
|
module Generation
|
@@ -25,22 +23,55 @@ module Antelope
|
|
25
23
|
# turns it into a hash, and passes that hash to each of the
|
26
24
|
# given generators.
|
27
25
|
#
|
26
|
+
# @param options [Hash] options.
|
28
27
|
# @param generators [Array<Generator>] a list of generators
|
29
28
|
# to use in generation.
|
30
29
|
# @param modifiers [Array<Array<(Symbol, #call)>>] a list of
|
31
30
|
# modifiers to apply to the grammar.
|
32
31
|
# @return [void]
|
33
|
-
def generate(
|
32
|
+
def generate(options = {},
|
33
|
+
generators = :guess,
|
34
34
|
modifiers = DEFAULT_MODIFIERS)
|
35
35
|
mods = modifiers.map(&:last).
|
36
36
|
map { |x| x.new(self) }
|
37
37
|
mods.map(&:call)
|
38
38
|
hash = Hash[modifiers.map(&:first).zip(mods)]
|
39
39
|
# This is when we'd generate
|
40
|
-
|
40
|
+
|
41
|
+
find_generators(generators, options).each do |gen|
|
41
42
|
gen.new(self, hash).generate
|
42
43
|
end
|
43
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Find the corresponding generators. If the first argument
|
49
|
+
# isn't `:guess`, it returns the first argument. Otherwise,
|
50
|
+
# it tries to "intelligently guess" by checking the type from
|
51
|
+
# the options _or_ the compiler. If it is unable to find the
|
52
|
+
# type, it will raise a {NoTypeError}.
|
53
|
+
#
|
54
|
+
# @raise [NoTypeError] if it could not determine the type of
|
55
|
+
# the generator.
|
56
|
+
# @param generators [Symbol, Array<Generator>]
|
57
|
+
# @param options [Hash]
|
58
|
+
# @return [Array<Generator>]
|
59
|
+
def find_generators(generators, options)
|
60
|
+
return generators unless generators == :guess
|
61
|
+
|
62
|
+
generators = [Generator::Output]
|
63
|
+
|
64
|
+
# command line precedence...
|
65
|
+
type = options[:type] || options["type"] ||
|
66
|
+
compiler.options.fetch(:type)
|
67
|
+
|
68
|
+
generators += DEFAULT_GENERATORS.fetch(type)
|
69
|
+
|
70
|
+
generators
|
71
|
+
|
72
|
+
rescue KeyError => e
|
73
|
+
raise NoTypeError, "Undefined type #{type}"
|
74
|
+
end
|
44
75
|
end
|
45
76
|
end
|
46
77
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module Antelope
|
4
|
+
module Ace
|
5
|
+
class Grammar
|
6
|
+
|
7
|
+
# Manages precedence for tokens.
|
8
|
+
module Precedences
|
9
|
+
|
10
|
+
# Accesses the generated precedence list. Lazily generates
|
11
|
+
# the precedence rules on the go, and then caches it.
|
12
|
+
#
|
13
|
+
# @return [Array<Ace::Precedence>]
|
14
|
+
def precedence
|
15
|
+
@_precedence ||= generate_precedence
|
16
|
+
end
|
17
|
+
|
18
|
+
# Finds a precedence rule for a given token. If no direct
|
19
|
+
# rule is defined for that token, it will check for a rule
|
20
|
+
# defined for the special symbol, `:_`. By default, there
|
21
|
+
# is always a rule defined for `:_`.
|
22
|
+
#
|
23
|
+
# @param token [Ace::Token, Symbol]
|
24
|
+
# @return [Ace::Precedence]
|
25
|
+
def precedence_for(token)
|
26
|
+
token = token.name if token.is_a?(Token)
|
27
|
+
|
28
|
+
set = Set.new([token, :_])
|
29
|
+
|
30
|
+
precedence.
|
31
|
+
select { |pr| set.intersect?(pr.tokens) }.
|
32
|
+
first
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Generates the precedence rules. Loops through the compiler
|
38
|
+
# given precedence settings, and then adds two default
|
39
|
+
# precedence rules; one for `:$` (level 0, nonassoc), and one
|
40
|
+
# for `:_` (level 1, nonassoc).
|
41
|
+
#
|
42
|
+
# @return [Array<Ace::Precedence>]
|
43
|
+
def generate_precedence
|
44
|
+
size = @compiler.options[:prec].size + 1
|
45
|
+
precedence = @compiler.options[:prec].
|
46
|
+
each_with_index.map do |prec, i|
|
47
|
+
Ace::Precedence.new(prec[0], prec[1..-1].to_set, size - i)
|
48
|
+
end
|
49
|
+
|
50
|
+
precedence <<
|
51
|
+
Ace::Precedence.new(:nonassoc, [:"$"].to_set, 0) <<
|
52
|
+
Ace::Precedence.new(:nonassoc, [:_].to_set, 1)
|
53
|
+
precedence.sort_by { |_| _.level }.reverse
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -3,32 +3,31 @@ module Antelope
|
|
3
3
|
class Grammar
|
4
4
|
|
5
5
|
# Defines a production.
|
6
|
-
#
|
7
|
-
# @!attribute [rw] label
|
8
|
-
# The label (or left-hand side) of the production. This
|
9
|
-
# should be a nonterminal.
|
10
|
-
#
|
11
|
-
# @return [Symbol]
|
12
|
-
# @!attribute [rw] items
|
13
|
-
# The body (or right-hand side) of the production. This can
|
14
|
-
# be array of terminals and nonterminals.
|
15
|
-
#
|
16
|
-
# @return [Array<Token>]
|
17
|
-
# @!attribute [rw] block
|
18
|
-
# The block of code to be executed when the production's right
|
19
|
-
# hand side is reduced.
|
20
|
-
#
|
21
|
-
# @return [String]
|
22
|
-
# @!attribute [rw] prec
|
23
|
-
# The presidence declaration for the production.
|
24
|
-
#
|
25
|
-
# @return [Ace::Presidence]
|
26
|
-
# @!attribute [rw] id
|
27
|
-
# The ID of the production. The starting production always
|
28
|
-
# has an ID of 0.
|
29
|
-
#
|
30
|
-
# @return [Numeric]
|
31
6
|
class Production < Struct.new(:label, :items, :block, :prec, :id)
|
7
|
+
# @!attribute [rw] label
|
8
|
+
# The label (or left-hand side) of the production. This
|
9
|
+
# should be a nonterminal.
|
10
|
+
#
|
11
|
+
# @return [Symbol]
|
12
|
+
# @!attribute [rw] items
|
13
|
+
# The body (or right-hand side) of the production. This can
|
14
|
+
# be array of terminals and nonterminals.
|
15
|
+
#
|
16
|
+
# @return [Array<Token>]
|
17
|
+
# @!attribute [rw] block
|
18
|
+
# The block of code to be executed when the production's right
|
19
|
+
# hand side is reduced.
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
# @!attribute [rw] prec
|
23
|
+
# The precedence declaration for the production.
|
24
|
+
#
|
25
|
+
# @return [Ace::Precedence]
|
26
|
+
# @!attribute [rw] id
|
27
|
+
# The ID of the production. The starting production always
|
28
|
+
# has an ID of 0.
|
29
|
+
#
|
30
|
+
# @return [Numeric]
|
32
31
|
|
33
32
|
# Creates a new production from a hash. The hash's keys
|
34
33
|
# correspond to the attributes on this class.
|
@@ -48,11 +48,11 @@ module Antelope
|
|
48
48
|
|
49
49
|
# Generates a production for a given compiler rule. Converts
|
50
50
|
# the tokens in the set to their {Token} counterparts,
|
51
|
-
# and then sets the
|
52
|
-
#
|
51
|
+
# and then sets the precedence for the production. If the
|
52
|
+
# precedence declaration from the compiler rule is empty,
|
53
53
|
# then it'll use the last terminal from the set to check for
|
54
|
-
#
|
55
|
-
# This is to make sure that every production has a
|
54
|
+
# precedence; otherwise, it'll use the precedence declaration.
|
55
|
+
# This is to make sure that every production has a precedence
|
56
56
|
# declaration.
|
57
57
|
#
|
58
58
|
# @param rule [Hash] the compiler's rule.
|
@@ -67,7 +67,7 @@ module Antelope
|
|
67
67
|
find_token(rule[:prec])
|
68
68
|
end
|
69
69
|
|
70
|
-
prec =
|
70
|
+
prec = precedence_for(prec)
|
71
71
|
|
72
72
|
Production.new(Token::Nonterminal.new(left), items,
|
73
73
|
rule[:block], prec, id + 1)
|
@@ -77,14 +77,14 @@ module Antelope
|
|
77
77
|
# hand side of the production is the `:$start` symbol, with
|
78
78
|
# the right hand side being the first rule's left-hand side
|
79
79
|
# and the terminal `$`. This production is automagically
|
80
|
-
# given the last
|
80
|
+
# given the last precedence, and an id of 0.
|
81
81
|
#
|
82
82
|
# @return [Production]
|
83
83
|
def default_production
|
84
84
|
Production.new(Token::Nonterminal.new(:$start), [
|
85
85
|
Token::Nonterminal.new(@compiler.rules.first[:label]),
|
86
86
|
Token::Terminal.new(:"$")
|
87
|
-
], "",
|
87
|
+
], "", precedence.last, 0)
|
88
88
|
end
|
89
89
|
|
90
90
|
# Finds a token based on its corresponding symbol. First
|
@@ -92,7 +92,7 @@ module Antelope
|
|
92
92
|
# tries to find it in the terminals; otherwise, if the symbol
|
93
93
|
# is `error`, it returns a {Token::Error}; if the symbol is
|
94
94
|
# `nothing` or `ε`, it returns a {Token::Epsilon}; if it's
|
95
|
-
# none of those, it raises an {
|
95
|
+
# none of those, it raises an {UndefinedTokenError}.
|
96
96
|
#
|
97
97
|
# @raise [UndefinedTokenError] if the token doesn't exist.
|
98
98
|
# @param value [String, Symbol, #intern] the token's symbol to
|
data/lib/antelope/ace/grammar.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "antelope/ace/grammar/terminals"
|
2
2
|
require "antelope/ace/grammar/productions"
|
3
|
-
require "antelope/ace/grammar/
|
3
|
+
require "antelope/ace/grammar/precedences"
|
4
4
|
require "antelope/ace/grammar/loading"
|
5
5
|
require "antelope/ace/grammar/generation"
|
6
6
|
require "antelope/ace/grammar/production"
|
@@ -9,13 +9,13 @@ module Antelope
|
|
9
9
|
module Ace
|
10
10
|
|
11
11
|
# Defines a grammar from an Ace file. This handles setting up
|
12
|
-
# productions, loading from files, terminals,
|
12
|
+
# productions, loading from files, terminals, precedence, and
|
13
13
|
# generation.
|
14
14
|
class Grammar
|
15
15
|
|
16
16
|
include Terminals
|
17
17
|
include Productions
|
18
|
-
include
|
18
|
+
include Precedences
|
19
19
|
include Loading
|
20
20
|
include Grammar::Generation
|
21
21
|
|
@@ -1,41 +1,41 @@
|
|
1
1
|
module Antelope
|
2
2
|
module Ace
|
3
3
|
|
4
|
-
# Defines a
|
4
|
+
# Defines a precedence. A precedence has a type, tokens, and a
|
5
5
|
# level.
|
6
|
-
class
|
6
|
+
class Precedence < Struct.new(:type, :tokens, :level)
|
7
7
|
|
8
8
|
# @!attribute [rw] type
|
9
|
-
# The type of
|
9
|
+
# The type of precedence level. This should be one of
|
10
10
|
# `:left`, `:right`, or `:nonassoc`.
|
11
11
|
#
|
12
12
|
# @return [Symbol] the type.
|
13
13
|
# @!attribute [rw] tokens
|
14
|
-
# An set of tokens that are on this specific
|
14
|
+
# An set of tokens that are on this specific precedence
|
15
15
|
# level. The tokens are identified as symbols. The special
|
16
16
|
# symbol, `:_`, represents any token.
|
17
17
|
#
|
18
18
|
# @return [Set<Symbol>] the tokens on this level.
|
19
19
|
# @!attribute [rw] level
|
20
20
|
# The level we're on. The higher the level, the higher the
|
21
|
-
#
|
21
|
+
# precedence.
|
22
22
|
|
23
23
|
include Comparable
|
24
24
|
|
25
25
|
# Compares the other object to this object. If the other object
|
26
|
-
# isn't a {
|
27
|
-
#
|
26
|
+
# isn't a {Precedence}, it returns nil. If the other
|
27
|
+
# precedence isn't on the same level as this one, then the
|
28
28
|
# levels are compared and the result of that is returned. If
|
29
|
-
# it is, however, the type is checked; if this
|
29
|
+
# it is, however, the type is checked; if this precedence is
|
30
30
|
# left associative, then it returns 1 (it is greater than the
|
31
|
-
# other); if this
|
32
|
-
# returns -1 (it is less than the other); if this
|
31
|
+
# other); if this precedence is right associative, then it
|
32
|
+
# returns -1 (it is less than the other); if this precedence is
|
33
33
|
# nonassociative, it returns 0 (it is equal to the other).
|
34
34
|
#
|
35
35
|
# @param other [Object] the object to compare to this one.
|
36
36
|
# @return [Numeric?]
|
37
37
|
def <=>(other)
|
38
|
-
return nil unless other.is_a?
|
38
|
+
return nil unless other.is_a? Precedence
|
39
39
|
if level != other.level
|
40
40
|
level <=> other.level
|
41
41
|
elsif type == :left
|