antelope 0.0.1 → 0.1.0
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/.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
|