antelope 0.1.1 → 0.1.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/.travis.yml +7 -0
- data/examples/deterministic.output +53 -139
- data/examples/example.output +159 -347
- data/examples/simple.output +50 -124
- data/lib/antelope/ace/compiler.rb +10 -1
- data/lib/antelope/ace/errors.rb +8 -0
- data/lib/antelope/ace/grammar/generation.rb +6 -1
- data/lib/antelope/ace/grammar/loading.rb +2 -0
- data/lib/antelope/ace/grammar/precedences.rb +3 -1
- data/lib/antelope/ace/grammar/production.rb +2 -0
- data/lib/antelope/ace/grammar/productions.rb +2 -0
- data/lib/antelope/ace/grammar/terminals.rb +2 -0
- data/lib/antelope/ace/grammar.rb +2 -0
- data/lib/antelope/ace/precedence.rb +2 -0
- data/lib/antelope/ace/scanner/first.rb +2 -0
- data/lib/antelope/ace/scanner/second.rb +3 -1
- data/lib/antelope/ace/scanner/third.rb +2 -0
- data/lib/antelope/ace/scanner.rb +2 -0
- data/lib/antelope/ace/token/epsilon.rb +4 -2
- data/lib/antelope/ace/token/error.rb +2 -0
- data/lib/antelope/ace/token/nonterminal.rb +2 -0
- data/lib/antelope/ace/token/terminal.rb +2 -0
- data/lib/antelope/ace/token.rb +2 -0
- data/lib/antelope/ace.rb +2 -0
- data/lib/antelope/cli.rb +2 -0
- data/lib/antelope/errors.rb +2 -0
- data/lib/antelope/generation/constructor/first.rb +2 -0
- data/lib/antelope/generation/constructor/follow.rb +5 -0
- data/lib/antelope/generation/constructor/nullable.rb +2 -0
- data/lib/antelope/generation/constructor.rb +2 -0
- data/lib/antelope/generation/errors.rb +2 -0
- data/lib/antelope/generation/recognizer/rule.rb +9 -0
- data/lib/antelope/generation/recognizer/state.rb +2 -0
- data/lib/antelope/generation/recognizer.rb +7 -2
- data/lib/antelope/generation/tableizer.rb +3 -2
- data/lib/antelope/generation.rb +2 -0
- data/lib/antelope/generator/output.rb +2 -0
- data/lib/antelope/generator/ruby.rb +2 -0
- data/lib/antelope/generator/templates/output.erb +21 -25
- data/lib/antelope/generator/templates/ruby.erb +1 -1
- data/lib/antelope/generator.rb +2 -0
- data/lib/antelope/version.rb +3 -1
- data/lib/antelope.rb +2 -0
- data/spec/antelope/ace/compiler_spec.rb +11 -1
- data/spec/antelope/constructor_spec.rb +127 -0
- data/spec/fixtures/simple.ace +22 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/grammar_helper.rb +15 -0
- metadata +9 -4
- data/spec/antelope/automaton_spec.rb +0 -29
data/examples/simple.output
CHANGED
@@ -6,30 +6,6 @@ Productions:
|
|
6
6
|
r → l
|
7
7
|
$start → e $
|
8
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
9
|
Precedence:
|
34
10
|
--- highest
|
35
11
|
nonassoc 1:
|
@@ -38,44 +14,7 @@ Precedence:
|
|
38
14
|
{$}
|
39
15
|
--- lowest
|
40
16
|
|
41
|
-
Table:
|
42
17
|
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
|
-
|
76
|
-
|
77
|
-
State 0:
|
78
|
-
rules:
|
79
18
|
0/n0: $start(0) → • e(0:1) $
|
80
19
|
{}
|
81
20
|
1/n1: e(0:1) → • l(0:2) "=" r(8:10)
|
@@ -88,105 +27,92 @@ State 0:
|
|
88
27
|
{}
|
89
28
|
5/n1: r(0:3) → • l(0:2)
|
90
29
|
{}
|
30
|
+
transitions:
|
31
|
+
e: State 1
|
32
|
+
l: State 2
|
33
|
+
r: State 3
|
34
|
+
IDENT: State 4
|
35
|
+
STAR: State 5
|
91
36
|
|
92
|
-
|
93
|
-
e : State 1
|
94
|
-
l : State 2
|
95
|
-
r : State 3
|
96
|
-
IDENT: State 4
|
97
|
-
STAR : State 5
|
98
|
-
|
99
|
-
State 1:
|
100
|
-
rules:
|
37
|
+
State 1:
|
101
38
|
6/n0: $start → e • $
|
102
39
|
{}
|
40
|
+
transitions:
|
41
|
+
$: State 7
|
103
42
|
|
104
|
-
|
105
|
-
$: State 7
|
106
|
-
|
107
|
-
State 2:
|
108
|
-
rules:
|
43
|
+
State 2:
|
109
44
|
7/n1: e → l • "=" r
|
110
45
|
{}
|
111
46
|
15/n1: r → l •
|
112
47
|
{$}
|
48
|
+
transitions:
|
49
|
+
EQUALS: State 8
|
50
|
+
reductions:
|
51
|
+
$: Rule 5
|
113
52
|
|
114
|
-
|
115
|
-
EQUALS: State 8
|
116
|
-
|
117
|
-
State 3:
|
118
|
-
rules:
|
53
|
+
State 3:
|
119
54
|
9/n1: e → r •
|
120
55
|
{$}
|
56
|
+
reductions:
|
57
|
+
$: Rule 2
|
121
58
|
|
122
|
-
|
123
|
-
|
124
|
-
State 4:
|
125
|
-
rules:
|
59
|
+
State 4:
|
126
60
|
10/n1: l → IDENT •
|
127
61
|
{$}
|
62
|
+
reductions:
|
63
|
+
$: Rule 3
|
128
64
|
|
129
|
-
|
130
|
-
|
131
|
-
State 5:
|
132
|
-
rules:
|
65
|
+
State 5:
|
133
66
|
11/n1: l → "*" • r
|
134
67
|
{}
|
135
|
-
12/n1: r(5:9) → • l(5:
|
68
|
+
12/n1: r(5:9) → • l(5:6)
|
136
69
|
{}
|
137
|
-
13/n1: l(5:
|
70
|
+
13/n1: l(5:6) → • IDENT
|
138
71
|
{}
|
139
|
-
14/n1: l(5:
|
72
|
+
14/n1: l(5:6) → • "*" r(5:9)
|
140
73
|
{}
|
74
|
+
transitions:
|
75
|
+
r: State 9
|
76
|
+
l: State 6
|
77
|
+
IDENT: State 4
|
78
|
+
STAR: State 5
|
141
79
|
|
142
|
-
|
143
|
-
r : State 9
|
144
|
-
l : State 2
|
145
|
-
IDENT: State 4
|
146
|
-
STAR : State 5
|
147
|
-
|
148
|
-
State 6:
|
149
|
-
rules:
|
80
|
+
State 6:
|
150
81
|
15/n1: r → l •
|
151
82
|
{$}
|
83
|
+
reductions:
|
84
|
+
$: Rule 5
|
152
85
|
|
153
|
-
|
154
|
-
|
155
|
-
State 7:
|
156
|
-
rules:
|
86
|
+
State 7:
|
157
87
|
16/n0: $start → e $ •
|
158
88
|
{}
|
89
|
+
accepting:
|
90
|
+
$: Rule 0
|
159
91
|
|
160
|
-
|
161
|
-
|
162
|
-
State 8:
|
163
|
-
rules:
|
92
|
+
State 8:
|
164
93
|
17/n1: e → l "=" • r
|
165
94
|
{}
|
166
|
-
18/n1: r(8:10) → • l(8:
|
95
|
+
18/n1: r(8:10) → • l(8:6)
|
167
96
|
{}
|
168
|
-
19/n1: l(8:
|
97
|
+
19/n1: l(8:6) → • IDENT
|
169
98
|
{}
|
170
|
-
20/n1: l(8:
|
99
|
+
20/n1: l(8:6) → • "*" r(5:9)
|
171
100
|
{}
|
101
|
+
transitions:
|
102
|
+
r: State 10
|
103
|
+
l: State 6
|
104
|
+
IDENT: State 4
|
105
|
+
STAR: State 5
|
172
106
|
|
173
|
-
|
174
|
-
r : State 10
|
175
|
-
l : State 2
|
176
|
-
IDENT: State 4
|
177
|
-
STAR : State 5
|
178
|
-
|
179
|
-
State 9:
|
180
|
-
rules:
|
107
|
+
State 9:
|
181
108
|
21/n1: l → "*" r •
|
182
109
|
{$}
|
110
|
+
reductions:
|
111
|
+
$: Rule 4
|
183
112
|
|
184
|
-
|
185
|
-
|
186
|
-
State 10:
|
187
|
-
rules:
|
113
|
+
State 10:
|
188
114
|
22/n1: e → l "=" r •
|
189
115
|
{$}
|
190
|
-
|
191
|
-
|
116
|
+
reductions:
|
117
|
+
$: Rule 1
|
192
118
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require "rubygems/requirement"
|
2
4
|
|
3
5
|
module Antelope
|
@@ -93,6 +95,13 @@ module Antelope
|
|
93
95
|
@options = { :terminals => [], :prec => [], :extra => {} }
|
94
96
|
end
|
95
97
|
|
98
|
+
# Pretty inspect.
|
99
|
+
#
|
100
|
+
# @return [String]
|
101
|
+
def inspect
|
102
|
+
"#<#{self.class} state=#{@state.inspect} options=#{@options.inspect}>"
|
103
|
+
end
|
104
|
+
|
96
105
|
# Runs the compiler on the input tokens. For each token,
|
97
106
|
# it calls `compile_<type>` with `<type>` being the first
|
98
107
|
# element of the token, with the remaining part of the array
|
@@ -279,7 +288,7 @@ module Antelope
|
|
279
288
|
|
280
289
|
unless required_version =~ antelope_version
|
281
290
|
raise IncompatibleVersionError,
|
282
|
-
"Grammar requires #{
|
291
|
+
"Grammar requires #{required}, " \
|
283
292
|
"have #{Antelope::VERSION}"
|
284
293
|
end
|
285
294
|
end
|
data/lib/antelope/ace/errors.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Antelope
|
2
4
|
module Ace
|
3
5
|
|
@@ -7,6 +9,12 @@ module Antelope
|
|
7
9
|
class Error < Antelope::Error
|
8
10
|
end
|
9
11
|
|
12
|
+
# Used primarily in the {Compiler}, this is raised when the
|
13
|
+
# version requirement of the Ace file doesn't match the running
|
14
|
+
# version of Ace.
|
15
|
+
class IncompatibleVersionError < Error
|
16
|
+
end
|
17
|
+
|
10
18
|
# Used primarily in the {Scanner}, this is raised when an input
|
11
19
|
# is malformed. The message should contain a snippet of the input
|
12
20
|
# which caused the error.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Antelope
|
2
4
|
module Ace
|
3
5
|
class Grammar
|
@@ -34,7 +36,10 @@ module Antelope
|
|
34
36
|
modifiers = DEFAULT_MODIFIERS)
|
35
37
|
mods = modifiers.map(&:last).
|
36
38
|
map { |x| x.new(self) }
|
37
|
-
mods.
|
39
|
+
mods.each do |mod|
|
40
|
+
puts "Running mod #{mod.class}..."
|
41
|
+
mod.call
|
42
|
+
end
|
38
43
|
hash = Hash[modifiers.map(&:first).zip(mods)]
|
39
44
|
# This is when we'd generate
|
40
45
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require "set"
|
2
4
|
|
3
5
|
module Antelope
|
@@ -28,7 +30,7 @@ module Antelope
|
|
28
30
|
set = Set.new([token, :_])
|
29
31
|
|
30
32
|
precedence.
|
31
|
-
select { |pr| set.
|
33
|
+
select { |pr| set.intersection(pr.tokens).any? }.
|
32
34
|
first
|
33
35
|
end
|
34
36
|
|
data/lib/antelope/ace/grammar.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Antelope
|
2
4
|
module Ace
|
3
5
|
class Scanner
|
@@ -86,7 +88,7 @@ module Antelope
|
|
86
88
|
#
|
87
89
|
# @return [Boolean] if it matched.
|
88
90
|
def scan_second_rule_part
|
89
|
-
if @scanner.scan(/([A-Za-z._-]+)(
|
91
|
+
if @scanner.scan(/([A-Za-z._-]+)(?!\:|[A-Za-z._-])/)
|
90
92
|
tokens << [:part, @scanner[1]]
|
91
93
|
end
|
92
94
|
end
|
data/lib/antelope/ace/scanner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Antelope
|
2
4
|
module Ace
|
3
5
|
class Token
|
@@ -7,9 +9,9 @@ module Antelope
|
|
7
9
|
# reduce to nothing.
|
8
10
|
class Epsilon < Token
|
9
11
|
# Initialize. Technically takes no arguments. Sets
|
10
|
-
# the name of the token to be
|
12
|
+
# the name of the token to be `:$empty`.
|
11
13
|
def initialize(*)
|
12
|
-
super :
|
14
|
+
super :"$empty"
|
13
15
|
end
|
14
16
|
|
15
17
|
# (see Token#epsilon?)
|
data/lib/antelope/ace/token.rb
CHANGED
data/lib/antelope/ace.rb
CHANGED
data/lib/antelope/cli.rb
CHANGED
data/lib/antelope/errors.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Antelope
|
2
4
|
module Generation
|
3
5
|
class Constructor
|
@@ -71,6 +73,9 @@ module Antelope
|
|
71
73
|
# This is going to be the output set.
|
72
74
|
set = Set.new
|
73
75
|
|
76
|
+
productions = grammar.states.map(&:rules).flatten.
|
77
|
+
inject(Set.new, :merge)
|
78
|
+
|
74
79
|
productions.each do |rule|
|
75
80
|
items = rule.right
|
76
81
|
|
@@ -136,6 +136,15 @@ module Antelope
|
|
136
136
|
!succ?
|
137
137
|
end
|
138
138
|
|
139
|
+
# The complete opposite of {#final?} - it checks to see if
|
140
|
+
# this is the first rule, as in no rule can exist before this
|
141
|
+
# one; i.e. the position is zero.
|
142
|
+
#
|
143
|
+
# @return [Boolean]
|
144
|
+
def start?
|
145
|
+
position.zero?
|
146
|
+
end
|
147
|
+
|
139
148
|
# Compares this rule to another object. If the other object
|
140
149
|
# is not a rule, it delegates the comparison. Otherwise, it
|
141
150
|
# converts both this and the other rule into arrays and
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require "antelope/generation/recognizer/rule"
|
2
4
|
require "antelope/generation/recognizer/state"
|
3
5
|
|
@@ -31,6 +33,7 @@ module Antelope
|
|
31
33
|
def initialize(grammar)
|
32
34
|
@grammar = grammar
|
33
35
|
@states = Set.new
|
36
|
+
@map = {}
|
34
37
|
end
|
35
38
|
|
36
39
|
# Runs the recognizer. After all states have been created, it
|
@@ -94,6 +97,7 @@ module Antelope
|
|
94
97
|
ns << succ
|
95
98
|
compute_closure(ns)
|
96
99
|
states << ns
|
100
|
+
@map[succ] = ns
|
97
101
|
ns
|
98
102
|
end
|
99
103
|
|
@@ -129,8 +133,9 @@ module Antelope
|
|
129
133
|
# @param rule [Rule]
|
130
134
|
# @yield [rule]
|
131
135
|
# @return [State]
|
132
|
-
def find_state_for(rule)
|
133
|
-
states.find { |state| state.include?(rule) } or yield(rule)
|
136
|
+
def find_state_for(rule, &block)
|
137
|
+
#states.find { |state| state.include?(rule) } or yield(rule)
|
138
|
+
@map.fetch(rule) { block.call(rule) }
|
134
139
|
end
|
135
140
|
|
136
141
|
# Changes the IDs of the states into a more friendly format.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Antelope
|
2
4
|
module Generation
|
3
5
|
|
@@ -96,8 +98,7 @@ module Antelope
|
|
96
98
|
|
97
99
|
case result
|
98
100
|
when 0
|
99
|
-
|
100
|
-
raise UnresolvableConflictError,
|
101
|
+
$stderr.puts \
|
101
102
|
"Could not determine move for #{on} in state #{state}"
|
102
103
|
when 1
|
103
104
|
@table[state][on] = rule_part
|
data/lib/antelope/generation.rb
CHANGED
@@ -5,16 +5,6 @@ Productions:
|
|
5
5
|
% end
|
6
6
|
% end
|
7
7
|
|
8
|
-
Productions, Again:
|
9
|
-
% constructor.productions.each do |production|
|
10
|
-
<%= production.to_s(false) %>
|
11
|
-
% end
|
12
|
-
|
13
|
-
FOLLOW:
|
14
|
-
% constructor.instance_variable_get(:@follows).each do |k, v|
|
15
|
-
<%= k %>: {<%= v.map(&:to_s).join(", ") %>}
|
16
|
-
% end
|
17
|
-
|
18
8
|
Precedence:
|
19
9
|
--- highest
|
20
10
|
% grammar.precedence.each do |pr|
|
@@ -23,28 +13,34 @@ Precedence:
|
|
23
13
|
% end
|
24
14
|
--- lowest
|
25
15
|
|
26
|
-
Table:
|
27
16
|
% len = tableizer.table.flatten.map(&:keys).flatten.map(&:size).max
|
17
|
+
% states = grammar.states.to_a
|
28
18
|
% tableizer.table.each_with_index do |v, i|
|
19
|
+
% state = states[i]
|
29
20
|
State <%= i %>:
|
30
|
-
% v.each do |token, action|
|
31
|
-
<%= "%-#{len}s" % token %>: <%= action[0] %> (<%= action[1] %>)
|
32
|
-
% end
|
33
|
-
% end
|
34
|
-
<%# PP.pp(Hash[tableizer.table.each_with_index.to_a.map(&:reverse)], _erbout) %>
|
35
|
-
|
36
|
-
% grammar.states.each do |state|
|
37
|
-
State <%= state.id %>:
|
38
|
-
rules:
|
39
21
|
% state.rules.each do |rule|
|
40
22
|
<%= rule %>
|
41
23
|
{<%= rule.lookahead.to_a.join(", ") %>}
|
42
24
|
% end
|
43
|
-
|
44
|
-
|
45
|
-
%
|
46
|
-
%
|
47
|
-
|
25
|
+
% transitions = v.each.select { |_, a| a[0] == :state }
|
26
|
+
% reductions = v.each.select { |_, a| a[0] == :reduce }
|
27
|
+
% accepting = v.each.select { |_, a| a[0] == :accept }
|
28
|
+
% conflicts = v.each.select { |_, (a, b)| a.is_a?(Array) }
|
29
|
+
% thing = [:transitions, :reductions, :accepting]
|
30
|
+
% num_type = {transitions: "State", reductions: "Rule", accepting: "Rule"}
|
31
|
+
% h = Hash[thing.zip([transitions, reductions, accepting])]
|
32
|
+
% h.each do |key, value|
|
33
|
+
% next unless value.any?
|
34
|
+
<%= key %>:
|
35
|
+
% value.each do |token, (_, name)|
|
36
|
+
<%= token %>: <%= num_type[key] %> <%= name %>
|
37
|
+
% end
|
38
|
+
% end
|
39
|
+
% if conflicts.any?
|
40
|
+
conflicts:
|
41
|
+
% conflicts.each do |token, (first, second)|
|
42
|
+
<%= token %>: <%= first.join(" ") %>/<%= second.join(" ") %>
|
43
|
+
% end
|
48
44
|
% end
|
49
45
|
|
50
46
|
% end
|
@@ -48,7 +48,7 @@ def parse(input)
|
|
48
48
|
when :reduce
|
49
49
|
production = PRODUCTIONS[action.last]
|
50
50
|
removing = stack.pop(production[1])
|
51
|
-
value =
|
51
|
+
value = instance_exec(*removing.map(&:first), &production[2])
|
52
52
|
goto = ACTION_TABLE[stack.last.last][production[0]]
|
53
53
|
stack.push([value, goto.last])
|
54
54
|
when :state
|