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