antelope 0.1.1 → 0.1.2

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