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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -0
  3. data/examples/deterministic.output +53 -139
  4. data/examples/example.output +159 -347
  5. data/examples/simple.output +50 -124
  6. data/lib/antelope/ace/compiler.rb +10 -1
  7. data/lib/antelope/ace/errors.rb +8 -0
  8. data/lib/antelope/ace/grammar/generation.rb +6 -1
  9. data/lib/antelope/ace/grammar/loading.rb +2 -0
  10. data/lib/antelope/ace/grammar/precedences.rb +3 -1
  11. data/lib/antelope/ace/grammar/production.rb +2 -0
  12. data/lib/antelope/ace/grammar/productions.rb +2 -0
  13. data/lib/antelope/ace/grammar/terminals.rb +2 -0
  14. data/lib/antelope/ace/grammar.rb +2 -0
  15. data/lib/antelope/ace/precedence.rb +2 -0
  16. data/lib/antelope/ace/scanner/first.rb +2 -0
  17. data/lib/antelope/ace/scanner/second.rb +3 -1
  18. data/lib/antelope/ace/scanner/third.rb +2 -0
  19. data/lib/antelope/ace/scanner.rb +2 -0
  20. data/lib/antelope/ace/token/epsilon.rb +4 -2
  21. data/lib/antelope/ace/token/error.rb +2 -0
  22. data/lib/antelope/ace/token/nonterminal.rb +2 -0
  23. data/lib/antelope/ace/token/terminal.rb +2 -0
  24. data/lib/antelope/ace/token.rb +2 -0
  25. data/lib/antelope/ace.rb +2 -0
  26. data/lib/antelope/cli.rb +2 -0
  27. data/lib/antelope/errors.rb +2 -0
  28. data/lib/antelope/generation/constructor/first.rb +2 -0
  29. data/lib/antelope/generation/constructor/follow.rb +5 -0
  30. data/lib/antelope/generation/constructor/nullable.rb +2 -0
  31. data/lib/antelope/generation/constructor.rb +2 -0
  32. data/lib/antelope/generation/errors.rb +2 -0
  33. data/lib/antelope/generation/recognizer/rule.rb +9 -0
  34. data/lib/antelope/generation/recognizer/state.rb +2 -0
  35. data/lib/antelope/generation/recognizer.rb +7 -2
  36. data/lib/antelope/generation/tableizer.rb +3 -2
  37. data/lib/antelope/generation.rb +2 -0
  38. data/lib/antelope/generator/output.rb +2 -0
  39. data/lib/antelope/generator/ruby.rb +2 -0
  40. data/lib/antelope/generator/templates/output.erb +21 -25
  41. data/lib/antelope/generator/templates/ruby.erb +1 -1
  42. data/lib/antelope/generator.rb +2 -0
  43. data/lib/antelope/version.rb +3 -1
  44. data/lib/antelope.rb +2 -0
  45. data/spec/antelope/ace/compiler_spec.rb +11 -1
  46. data/spec/antelope/constructor_spec.rb +127 -0
  47. data/spec/fixtures/simple.ace +22 -0
  48. data/spec/spec_helper.rb +1 -0
  49. data/spec/support/grammar_helper.rb +15 -0
  50. metadata +9 -4
  51. data/spec/antelope/automaton_spec.rb +0 -29
@@ -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
- transitions:
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
- transitions:
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
- transitions:
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
- transitions:
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
- transitions:
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:2)
68
+ 12/n1: r(5:9) → • l(5:6)
136
69
  {}
137
- 13/n1: l(5:2) → • IDENT
70
+ 13/n1: l(5:6) → • IDENT
138
71
  {}
139
- 14/n1: l(5:2) → • "*" r(5:9)
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
- transitions:
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
- transitions:
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
- transitions:
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:2)
95
+ 18/n1: r(8:10) → • l(8:6)
167
96
  {}
168
- 19/n1: l(8:2) → • IDENT
97
+ 19/n1: l(8:6) → • IDENT
169
98
  {}
170
- 20/n1: l(8:2) → • "*" r(5:9)
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
- transitions:
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
- transitions:
185
-
186
- State 10:
187
- rules:
113
+ State 10:
188
114
  22/n1: e → l "=" r •
189
115
  {$}
190
-
191
- transitions:
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 #{args[0]}, " \
291
+ "Grammar requires #{required}, " \
283
292
  "have #{Antelope::VERSION}"
284
293
  end
285
294
  end
@@ -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.map(&:call)
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
  module Antelope
2
4
  module Ace
3
5
  class Grammar
@@ -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.intersect?(pr.tokens) }.
33
+ select { |pr| set.intersection(pr.tokens).any? }.
32
34
  first
33
35
  end
34
36
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Grammar
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Grammar
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Grammar
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "antelope/ace/grammar/terminals"
2
4
  require "antelope/ace/grammar/productions"
3
5
  require "antelope/ace/grammar/precedences"
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Scanner
@@ -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
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Scanner
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "strscan"
2
4
  require "antelope/ace/scanner/first"
3
5
  require "antelope/ace/scanner/second"
@@ -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 `:epsilon`.
12
+ # the name of the token to be `:$empty`.
11
13
  def initialize(*)
12
- super :epsilon
14
+ super :"$empty"
13
15
  end
14
16
 
15
17
  # (see Token#epsilon?)
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Token
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Token
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Ace
3
5
  class Token
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "antelope/ace/token/nonterminal"
2
4
  require "antelope/ace/token/terminal"
3
5
  require "antelope/ace/token/epsilon"
data/lib/antelope/ace.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "antelope/ace/errors"
2
4
  require "antelope/ace/scanner"
3
5
  require "antelope/ace/compiler"
data/lib/antelope/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "thor"
2
4
 
3
5
  module Antelope
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
 
3
5
  # Every error in antelope inherits this error class.
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Generation
3
5
  class Constructor
@@ -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
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Generation
3
5
  class Constructor
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "set"
2
4
  require "antelope/generation/constructor/nullable"
3
5
  require "antelope/generation/constructor/first"
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Antelope
2
4
  module Generation
3
5
 
@@ -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 "forwardable"
2
4
  require "securerandom"
3
5
 
@@ -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
- p v, terminal, @rules[rule_part[1]].precedence
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
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "antelope/generation/errors"
2
4
  require "antelope/generation/constructor"
3
5
  require "antelope/generation/recognizer"
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "pp"
2
4
 
3
5
  module Antelope
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "pp"
2
4
 
3
5
  module Antelope
@@ -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
- transitions:
45
- % max = state.transitions.keys.map(&:length).max || 0
46
- % state.transitions.each do |on, to|
47
- <%= "%-#{max}s" % on %>: State <%= to.id %>
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 = production[2].call(*removing.map(&:first))
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
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require "antelope/generator/output"
2
4
  require "antelope/generator/ruby"
3
5
  require "erb"