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