antelope 0.1.4 → 0.1.5
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/examples/deterministic.output +85 -80
- data/examples/example.output +251 -243
- data/examples/simple.output +69 -57
- data/lib/antelope/ace/grammar.rb +0 -1
- data/lib/antelope/ace/production.rb +57 -0
- data/lib/antelope/ace/token.rb +5 -0
- data/lib/antelope/ace.rb +1 -0
- data/lib/antelope/generation/constructor/follow.rb +3 -9
- data/lib/antelope/generation/constructor.rb +21 -6
- data/lib/antelope/generation/recognizer/rule.rb +18 -9
- data/lib/antelope/generation/recognizer/state.rb +10 -1
- data/lib/antelope/generation/recognizer.rb +2 -4
- data/lib/antelope/version.rb +1 -1
- data/spec/antelope/constructor_spec.rb +4 -0
- metadata +3 -3
- data/lib/antelope/ace/grammar/production.rb +0 -48
data/examples/simple.output
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
Productions:
|
2
|
-
|
3
|
-
e → r
|
4
|
-
|
5
|
-
l →
|
6
|
-
|
7
|
-
|
2
|
+
0 $start(0) → e(0:1) $
|
3
|
+
1 e(0:1) → l(0:2) "=" r(7:10)
|
4
|
+
2 e(0:1) → r(0:3)
|
5
|
+
3 l(0:2) → IDENT
|
6
|
+
4 l(0:2) → "*" r(5:8)
|
7
|
+
5 r(0:3) → l(0:2)
|
8
|
+
5 r(5:8) → l(5:9)
|
9
|
+
3 l(5:9) → IDENT
|
10
|
+
4 l(5:9) → "*" r(5:8)
|
11
|
+
5 r(7:10) → l(7:9)
|
12
|
+
3 l(7:9) → IDENT
|
13
|
+
4 l(7:9) → "*" r(5:8)
|
14
|
+
|
15
|
+
Nontemrinals:
|
16
|
+
["$start(0)", "e(0:1)", "l(0:2)", "r(0:3)", "r(5:8)", "l(5:9)", "r(7:10)", "l(7:9)"]
|
8
17
|
|
9
18
|
Precedence:
|
10
19
|
--- highest
|
@@ -15,18 +24,18 @@ Precedence:
|
|
15
24
|
--- lowest
|
16
25
|
|
17
26
|
State 0:
|
18
|
-
0/n0: $start
|
19
|
-
{}
|
20
|
-
1/n1: e
|
21
|
-
{}
|
22
|
-
2/n1: e
|
23
|
-
{}
|
24
|
-
3/n1: l
|
25
|
-
{}
|
26
|
-
4/n1: l
|
27
|
-
{}
|
28
|
-
5/n1: r
|
29
|
-
{}
|
27
|
+
0/n0: $start → • e $
|
28
|
+
{} ($start)
|
29
|
+
1/n1: e → • l "=" r
|
30
|
+
{} (e)
|
31
|
+
2/n1: e → • r
|
32
|
+
{} (e)
|
33
|
+
3/n1: l → • IDENT
|
34
|
+
{} (l)
|
35
|
+
4/n1: l → • "*" r
|
36
|
+
{} (l)
|
37
|
+
5/n1: r → • l
|
38
|
+
{} (r)
|
30
39
|
transitions:
|
31
40
|
e: State 1
|
32
41
|
l: State 2
|
@@ -36,83 +45,86 @@ Precedence:
|
|
36
45
|
|
37
46
|
State 1:
|
38
47
|
6/n0: $start → e • $
|
39
|
-
{}
|
48
|
+
{} ($start)
|
40
49
|
transitions:
|
41
|
-
$: State
|
50
|
+
$: State 6
|
42
51
|
|
43
52
|
State 2:
|
44
53
|
7/n1: e → l • "=" r
|
45
|
-
{}
|
46
|
-
|
47
|
-
{$}
|
54
|
+
{} (e)
|
55
|
+
8/n1: r → l •
|
56
|
+
{$} (r)
|
48
57
|
transitions:
|
49
|
-
EQUALS: State
|
58
|
+
EQUALS: State 7
|
50
59
|
reductions:
|
51
60
|
$: Rule 5
|
52
61
|
|
53
62
|
State 3:
|
54
63
|
9/n1: e → r •
|
55
|
-
{$}
|
64
|
+
{$} (e)
|
56
65
|
reductions:
|
57
66
|
$: Rule 2
|
58
67
|
|
59
68
|
State 4:
|
60
69
|
10/n1: l → IDENT •
|
61
|
-
{$}
|
70
|
+
{"=", $} (l)
|
62
71
|
reductions:
|
72
|
+
EQUALS: Rule 3
|
63
73
|
$: Rule 3
|
64
74
|
|
65
75
|
State 5:
|
66
76
|
11/n1: l → "*" • r
|
67
|
-
{}
|
68
|
-
12/n1: r
|
69
|
-
{}
|
70
|
-
13/n1: l
|
71
|
-
{}
|
72
|
-
14/n1: l
|
73
|
-
{}
|
77
|
+
{} (l)
|
78
|
+
12/n1: r → • l
|
79
|
+
{} (r)
|
80
|
+
13/n1: l → • IDENT
|
81
|
+
{} (l)
|
82
|
+
14/n1: l → • "*" r
|
83
|
+
{} (l)
|
74
84
|
transitions:
|
75
|
-
r: State
|
76
|
-
l: State
|
85
|
+
r: State 8
|
86
|
+
l: State 9
|
77
87
|
IDENT: State 4
|
78
88
|
STAR: State 5
|
79
89
|
|
80
90
|
State 6:
|
81
|
-
15/
|
82
|
-
{$
|
83
|
-
reductions:
|
84
|
-
$: Rule 5
|
85
|
-
|
86
|
-
State 7:
|
87
|
-
16/n0: $start → e $ •
|
88
|
-
{}
|
91
|
+
15/n0: $start → e $ •
|
92
|
+
{} ($start)
|
89
93
|
accepting:
|
90
94
|
$: Rule 0
|
91
95
|
|
92
|
-
State
|
93
|
-
|
94
|
-
{}
|
95
|
-
|
96
|
-
{}
|
97
|
-
|
98
|
-
{}
|
99
|
-
|
100
|
-
{}
|
96
|
+
State 7:
|
97
|
+
16/n1: e → l "=" • r
|
98
|
+
{} (e)
|
99
|
+
17/n1: r → • l
|
100
|
+
{} (r)
|
101
|
+
18/n1: l → • IDENT
|
102
|
+
{} (l)
|
103
|
+
19/n1: l → • "*" r
|
104
|
+
{} (l)
|
101
105
|
transitions:
|
102
106
|
r: State 10
|
103
|
-
l: State
|
107
|
+
l: State 9
|
104
108
|
IDENT: State 4
|
105
109
|
STAR: State 5
|
106
110
|
|
107
|
-
State
|
108
|
-
|
109
|
-
{$}
|
111
|
+
State 8:
|
112
|
+
20/n1: l → "*" r •
|
113
|
+
{"=", $} (l)
|
110
114
|
reductions:
|
115
|
+
EQUALS: Rule 4
|
111
116
|
$: Rule 4
|
112
117
|
|
118
|
+
State 9:
|
119
|
+
21/n1: r → l •
|
120
|
+
{"=", $} (r)
|
121
|
+
reductions:
|
122
|
+
EQUALS: Rule 5
|
123
|
+
$: Rule 5
|
124
|
+
|
113
125
|
State 10:
|
114
126
|
22/n1: e → l "=" r •
|
115
|
-
{$}
|
127
|
+
{$} (e)
|
116
128
|
reductions:
|
117
129
|
$: Rule 1
|
118
130
|
|
data/lib/antelope/ace/grammar.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Antelope
|
4
|
+
module Ace
|
5
|
+
|
6
|
+
# Defines a production.
|
7
|
+
class Production < Struct.new(:label, :items, :block, :prec, :id)
|
8
|
+
# @!attribute [rw] label
|
9
|
+
# The label (or left-hand side) of the production. This
|
10
|
+
# should be a nonterminal.
|
11
|
+
#
|
12
|
+
# @return [Symbol]
|
13
|
+
# @!attribute [rw] items
|
14
|
+
# The body (or right-hand side) of the production. This can
|
15
|
+
# be array of terminals and nonterminals.
|
16
|
+
#
|
17
|
+
# @return [Array<Token>]
|
18
|
+
# @!attribute [rw] block
|
19
|
+
# The block of code to be executed when the production's right
|
20
|
+
# hand side is reduced.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
# @!attribute [rw] prec
|
24
|
+
# The precedence declaration for the production.
|
25
|
+
#
|
26
|
+
# @return [Ace::Precedence]
|
27
|
+
# @!attribute [rw] id
|
28
|
+
# The ID of the production. The starting production always
|
29
|
+
# has an ID of 0.
|
30
|
+
#
|
31
|
+
# @return [Numeric]
|
32
|
+
|
33
|
+
# Creates a new production from a hash. The hash's keys
|
34
|
+
# correspond to the attributes on this class.
|
35
|
+
#
|
36
|
+
# @param hash [Hash<(Symbol, Object)>]
|
37
|
+
def self.from_hash(hash)
|
38
|
+
new(hash[:label] || hash["label"],
|
39
|
+
hash[:items] || hash["items"],
|
40
|
+
hash[:block] || hash["block"],
|
41
|
+
hash[:prec] || hash["prec"],
|
42
|
+
hash[:id] || hash["id"])
|
43
|
+
end
|
44
|
+
|
45
|
+
# Create a new version of the production with duplicated values.
|
46
|
+
#
|
47
|
+
# @return [Production]
|
48
|
+
def clone
|
49
|
+
Production.new(label.dup,
|
50
|
+
items.map(&:dup),
|
51
|
+
block.dup,
|
52
|
+
prec.dup,
|
53
|
+
id)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/antelope/ace/token.rb
CHANGED
@@ -110,6 +110,11 @@ module Antelope
|
|
110
110
|
buf
|
111
111
|
end
|
112
112
|
|
113
|
+
def inspect
|
114
|
+
"#<#{self.class} from=#{from.id if from} to=#{to.id if to} " \
|
115
|
+
"name=#{name.inspect} value=#{@value.inspect}>"
|
116
|
+
end
|
117
|
+
|
113
118
|
# Compares this class to any other object. If the other object
|
114
119
|
# is a token, it converts both this class and the other object
|
115
120
|
# to an array and compares the array. Otherwise, it delegates
|
data/lib/antelope/ace.rb
CHANGED
@@ -68,16 +68,10 @@ module Antelope
|
|
68
68
|
# @see Nullable#nullable?
|
69
69
|
def generate_follow_set(token)
|
70
70
|
# Set it to the empty set so we don't end up recursing.
|
71
|
-
@follows[token] = Set.new
|
72
|
-
|
73
|
-
# This is going to be the output set.
|
74
|
-
set = Set.new
|
75
|
-
|
76
|
-
productions = grammar.states.map(&:rules).flatten.
|
77
|
-
inject(Set.new, :merge)
|
71
|
+
set = @follows[token] = Set.new
|
78
72
|
|
79
73
|
productions.each do |rule|
|
80
|
-
items = rule.
|
74
|
+
items = rule.items
|
81
75
|
|
82
76
|
# Find all of the positions within the rule that our token
|
83
77
|
# occurs, and then increment that position by one.
|
@@ -95,7 +89,7 @@ module Antelope
|
|
95
89
|
if pos == items.size || nullable?(items[pos..-1])
|
96
90
|
# Then add the FOLLOW set of the left-hand side to our
|
97
91
|
# set.
|
98
|
-
set.merge follow(rule.
|
92
|
+
set.merge follow(rule.label)
|
99
93
|
end
|
100
94
|
end
|
101
95
|
end
|
@@ -21,6 +21,9 @@ module Antelope
|
|
21
21
|
# @return [Ace::Grammar]
|
22
22
|
attr_reader :grammar
|
23
23
|
|
24
|
+
# The augmented productions generated by the constructor.
|
25
|
+
#
|
26
|
+
# @return [Set<Ace::Production>]
|
24
27
|
attr_reader :productions
|
25
28
|
|
26
29
|
# Initialize.
|
@@ -56,22 +59,29 @@ module Antelope
|
|
56
59
|
# @return [void]
|
57
60
|
def augment_state(state)
|
58
61
|
state.rules.select { |x| x.position.zero? }.each do |rule|
|
62
|
+
production = rule.production.clone
|
63
|
+
production.items = []
|
64
|
+
|
59
65
|
current_state = state
|
60
66
|
|
61
|
-
|
62
|
-
|
67
|
+
production.label.from = state
|
68
|
+
production.label.to = state.transitions[rule.left.name]
|
63
69
|
|
64
70
|
rule.right.each_with_index do |part, pos|
|
65
71
|
transition = current_state.transitions[part.name]
|
72
|
+
new_item = part.dup
|
73
|
+
|
66
74
|
if part.nonterminal?
|
67
|
-
|
68
|
-
|
75
|
+
new_item.from = current_state
|
76
|
+
new_item.to = transition
|
69
77
|
end
|
70
78
|
|
79
|
+
production.items << new_item
|
80
|
+
|
71
81
|
current_state = transition
|
72
82
|
end
|
73
83
|
|
74
|
-
productions <<
|
84
|
+
productions << production
|
75
85
|
end
|
76
86
|
end
|
77
87
|
|
@@ -88,6 +98,10 @@ module Antelope
|
|
88
98
|
state.rules.select { |x| x.position.zero? }.each do |rule|
|
89
99
|
current_state = state
|
90
100
|
|
101
|
+
label = rule.left.dup
|
102
|
+
label.from = state
|
103
|
+
label.to = state.transitions[label.name]
|
104
|
+
|
91
105
|
rule.right.each do |part|
|
92
106
|
transition = current_state.transitions[part.name]
|
93
107
|
current_state = transition
|
@@ -95,7 +109,8 @@ module Antelope
|
|
95
109
|
|
96
110
|
final = current_state.rule_for(rule)
|
97
111
|
|
98
|
-
final.lookahead =
|
112
|
+
final.lookahead = Set.new unless final.lookahead
|
113
|
+
final.lookahead.merge follow(label)
|
99
114
|
end
|
100
115
|
end
|
101
116
|
|
@@ -18,8 +18,8 @@ module Antelope
|
|
18
18
|
|
19
19
|
# The right-hand side of the rule.
|
20
20
|
#
|
21
|
-
# @return [Ace::Token]
|
22
|
-
|
21
|
+
# @return [Array<Ace::Token>]
|
22
|
+
attr_accessor :right
|
23
23
|
|
24
24
|
# The current position inside of the rule.
|
25
25
|
#
|
@@ -28,7 +28,7 @@ module Antelope
|
|
28
28
|
|
29
29
|
# The block to be executed on production match.
|
30
30
|
#
|
31
|
-
# @deprecated Use {Ace::
|
31
|
+
# @deprecated Use {Ace::Production#block} instead.
|
32
32
|
# @return [String]
|
33
33
|
attr_reader :block
|
34
34
|
|
@@ -52,14 +52,14 @@ module Antelope
|
|
52
52
|
|
53
53
|
# The associated production.
|
54
54
|
#
|
55
|
-
# @return [Ace::
|
55
|
+
# @return [Ace::Production]
|
56
56
|
attr_reader :production
|
57
57
|
|
58
58
|
include Comparable
|
59
59
|
|
60
60
|
# Initialize the rule.
|
61
61
|
#
|
62
|
-
# @param production [Ace::
|
62
|
+
# @param production [Ace::Production] the production
|
63
63
|
# that this rule is based off of.
|
64
64
|
# @param position [Numeric] the position that this rule is in
|
65
65
|
# the production.
|
@@ -74,9 +74,9 @@ module Antelope
|
|
74
74
|
@id = SecureRandom.hex
|
75
75
|
|
76
76
|
if inherited
|
77
|
-
@right = inherited
|
77
|
+
@left, @right = inherited
|
78
78
|
else
|
79
|
-
@right = production.items.map(&:dup)
|
79
|
+
@right = production.items.map(&:dup)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -115,7 +115,7 @@ module Antelope
|
|
115
115
|
#
|
116
116
|
# @return [Rule]
|
117
117
|
def succ
|
118
|
-
Rule.new(production, position + 1)
|
118
|
+
Rule.new(production, position + 1, [left, right])
|
119
119
|
end
|
120
120
|
|
121
121
|
# Checks to see if a rule can exist after this one; i.e. the
|
@@ -175,6 +175,15 @@ module Antelope
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
+
# Produces a clone of the rule; any modifications made to the
|
179
|
+
# contents of that rule do not reflect the contents of this
|
180
|
+
# rule.
|
181
|
+
#
|
182
|
+
# @return [Rule]
|
183
|
+
def clone
|
184
|
+
Rule.new(production, position)
|
185
|
+
end
|
186
|
+
|
178
187
|
# Generates a hash for this class.
|
179
188
|
#
|
180
189
|
# @note This is not intended for use. It is only defined to be
|
@@ -194,7 +203,7 @@ module Antelope
|
|
194
203
|
# @private
|
195
204
|
# @return [Array<(Ace::Token::Nonterminal, Array<Ace::Token>, Numeric)>]
|
196
205
|
def to_a
|
197
|
-
[left, right, position]
|
206
|
+
[left, right, position].flatten
|
198
207
|
end
|
199
208
|
end
|
200
209
|
end
|
@@ -87,7 +87,7 @@ module Antelope
|
|
87
87
|
# @return [self]
|
88
88
|
def <<(rule)
|
89
89
|
if rule.is_a? State
|
90
|
-
rule.rules.each { |r| self << r }
|
90
|
+
rule.rules.map(&:clone).each { |r| self << r }
|
91
91
|
elsif rule.is_a? Rule
|
92
92
|
rules << rule unless rules.include? rule
|
93
93
|
else
|
@@ -100,6 +100,15 @@ module Antelope
|
|
100
100
|
|
101
101
|
alias_method :push, :<<
|
102
102
|
|
103
|
+
def ===(other)
|
104
|
+
return super unless other.is_a? State
|
105
|
+
|
106
|
+
other_rules = other.rules.to_a
|
107
|
+
other.transitions == transitions and
|
108
|
+
rules.each_with_index.
|
109
|
+
all? { |rule, i| rule === other_rules[i] }
|
110
|
+
end
|
111
|
+
|
103
112
|
end
|
104
113
|
end
|
105
114
|
end
|
@@ -93,17 +93,15 @@ module Antelope
|
|
93
93
|
state.rules.each do |rule|
|
94
94
|
next unless rule.succ?
|
95
95
|
transitional = find_state_for(rule.succ) do |succ|
|
96
|
-
ns = State.new
|
97
|
-
ns << succ
|
96
|
+
ns = State.new << succ
|
98
97
|
compute_closure(ns)
|
99
|
-
states << ns
|
100
98
|
@map[succ] = ns
|
101
|
-
ns
|
102
99
|
end
|
103
100
|
|
104
101
|
if state.transitions[rule.active.name]
|
105
102
|
state.transitions[rule.active.name].merge! transitional
|
106
103
|
else
|
104
|
+
states << transitional
|
107
105
|
state.transitions[rule.active.name] = transitional
|
108
106
|
end
|
109
107
|
end
|
data/lib/antelope/version.rb
CHANGED
@@ -111,6 +111,10 @@ describe Generation::Constructor do
|
|
111
111
|
let(:grammar) { with_recognizer }
|
112
112
|
let(:nonterminal) { token(:l, nil, :nonterminal) }
|
113
113
|
|
114
|
+
before do
|
115
|
+
subject.productions.merge grammar.productions.values.flatten
|
116
|
+
end
|
117
|
+
|
114
118
|
it "generates a set" do
|
115
119
|
expect(subject.follow(nonterminal)).to eq [
|
116
120
|
token(:EQUALS, "="),
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: antelope
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Rodi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -126,10 +126,10 @@ files:
|
|
126
126
|
- lib/antelope/ace/grammar/generation.rb
|
127
127
|
- lib/antelope/ace/grammar/loading.rb
|
128
128
|
- lib/antelope/ace/grammar/precedences.rb
|
129
|
-
- lib/antelope/ace/grammar/production.rb
|
130
129
|
- lib/antelope/ace/grammar/productions.rb
|
131
130
|
- lib/antelope/ace/grammar/terminals.rb
|
132
131
|
- lib/antelope/ace/precedence.rb
|
132
|
+
- lib/antelope/ace/production.rb
|
133
133
|
- lib/antelope/ace/scanner.rb
|
134
134
|
- lib/antelope/ace/scanner/first.rb
|
135
135
|
- lib/antelope/ace/scanner/second.rb
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Antelope
|
4
|
-
module Ace
|
5
|
-
class Grammar
|
6
|
-
|
7
|
-
# Defines a production.
|
8
|
-
class Production < Struct.new(:label, :items, :block, :prec, :id)
|
9
|
-
# @!attribute [rw] label
|
10
|
-
# The label (or left-hand side) of the production. This
|
11
|
-
# should be a nonterminal.
|
12
|
-
#
|
13
|
-
# @return [Symbol]
|
14
|
-
# @!attribute [rw] items
|
15
|
-
# The body (or right-hand side) of the production. This can
|
16
|
-
# be array of terminals and nonterminals.
|
17
|
-
#
|
18
|
-
# @return [Array<Token>]
|
19
|
-
# @!attribute [rw] block
|
20
|
-
# The block of code to be executed when the production's right
|
21
|
-
# hand side is reduced.
|
22
|
-
#
|
23
|
-
# @return [String]
|
24
|
-
# @!attribute [rw] prec
|
25
|
-
# The precedence declaration for the production.
|
26
|
-
#
|
27
|
-
# @return [Ace::Precedence]
|
28
|
-
# @!attribute [rw] id
|
29
|
-
# The ID of the production. The starting production always
|
30
|
-
# has an ID of 0.
|
31
|
-
#
|
32
|
-
# @return [Numeric]
|
33
|
-
|
34
|
-
# Creates a new production from a hash. The hash's keys
|
35
|
-
# correspond to the attributes on this class.
|
36
|
-
#
|
37
|
-
# @param hash [Hash<(Symbol, Object)>]
|
38
|
-
def self.from_hash(hash)
|
39
|
-
new(hash[:label] || hash["label"],
|
40
|
-
hash[:items] || hash["items"],
|
41
|
-
hash[:block] || hash["block"],
|
42
|
-
hash[:prec] || hash["prec"],
|
43
|
-
hash[:id] || hash["id"])
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|