antelope 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,19 @@
1
1
  Productions:
2
- el "=" r
3
- e → r
4
- lIDENT
5
- l → "*" r
6
- rl
7
- $starte $
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(0) → • e(0:1) $
19
- {}
20
- 1/n1: e(0:1) → • l(0:2) "=" r(8:10)
21
- {}
22
- 2/n1: e(0:1) → • r(0:3)
23
- {}
24
- 3/n1: l(0:2) → • IDENT
25
- {}
26
- 4/n1: l(0:2) → • "*" r(5:9)
27
- {}
28
- 5/n1: r(0:3) → • l(0:2)
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 7
50
+ $: State 6
42
51
 
43
52
  State 2:
44
53
  7/n1: e → l • "=" r
45
- {}
46
- 15/n1: r → l •
47
- {$}
54
+ {} (e)
55
+ 8/n1: r → l •
56
+ {$} (r)
48
57
  transitions:
49
- EQUALS: State 8
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(5:9) → • l(5:6)
69
- {}
70
- 13/n1: l(5:6) → • IDENT
71
- {}
72
- 14/n1: l(5:6) → • "*" r(5:9)
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 9
76
- l: State 6
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/n1: rl
82
- {$}
83
- reductions:
84
- $: Rule 5
85
-
86
- State 7:
87
- 16/n0: $start → e $ •
88
- {}
91
+ 15/n0: $starte $
92
+ {} ($start)
89
93
  accepting:
90
94
  $: Rule 0
91
95
 
92
- State 8:
93
- 17/n1: e → l "=" • r
94
- {}
95
- 18/n1: r(8:10) → • l(8:6)
96
- {}
97
- 19/n1: l(8:6) → • IDENT
98
- {}
99
- 20/n1: l(8:6) → • "*" r(5:9)
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 6
107
+ l: State 9
104
108
  IDENT: State 4
105
109
  STAR: State 5
106
110
 
107
- State 9:
108
- 21/n1: l → "*" r •
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
 
@@ -5,7 +5,6 @@ require "antelope/ace/grammar/productions"
5
5
  require "antelope/ace/grammar/precedences"
6
6
  require "antelope/ace/grammar/loading"
7
7
  require "antelope/ace/grammar/generation"
8
- require "antelope/ace/grammar/production"
9
8
 
10
9
  module Antelope
11
10
  module Ace
@@ -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
@@ -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
@@ -5,6 +5,7 @@ require "antelope/ace/scanner"
5
5
  require "antelope/ace/compiler"
6
6
  require "antelope/ace/token"
7
7
  require "antelope/ace/precedence"
8
+ require "antelope/ace/production"
8
9
  require "antelope/ace/grammar"
9
10
 
10
11
  module Antelope
@@ -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.right
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.left)
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
- rule.left.from = state
62
- rule.left.to = state.transitions[rule.left.name]
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
- part.from = current_state
68
- part.to = transition
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 << rule
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 = follow(rule.left)
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
- attr_reader :right
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::Grammar::Production#block} instead.
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::Grammar::Production]
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::Grammar::Production] the production
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).freeze
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Antelope
4
4
  # The current running version of antelope.
5
- VERSION = "0.1.4".freeze
5
+ VERSION = "0.1.5".freeze
6
6
  end
@@ -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
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-23 00:00:00.000000000 Z
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