antelope 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +25 -23
  3. data/.rspec +3 -3
  4. data/.travis.yml +10 -9
  5. data/.yardopts +7 -7
  6. data/CONTRIBUTING.md +38 -38
  7. data/GENERATORS.md +124 -124
  8. data/Gemfile +7 -7
  9. data/LICENSE.txt +22 -22
  10. data/README.md +104 -104
  11. data/Rakefile +2 -2
  12. data/TODO.md +58 -58
  13. data/antelope.gemspec +28 -28
  14. data/bin/antelope +7 -7
  15. data/examples/deterministic.ace +35 -35
  16. data/examples/example.ace +51 -50
  17. data/examples/example.err +192 -0
  18. data/examples/{example.output → example.inf} +384 -385
  19. data/examples/liquidscript.ace +233 -162
  20. data/examples/simple.ace +22 -22
  21. data/lib/antelope/ace/compiler.rb +334 -334
  22. data/lib/antelope/ace/errors.rb +48 -48
  23. data/lib/antelope/ace/grammar/generation.rb +80 -80
  24. data/lib/antelope/ace/grammar/loading.rb +53 -53
  25. data/lib/antelope/ace/grammar/precedences.rb +68 -65
  26. data/lib/antelope/ace/grammar/productions.rb +156 -150
  27. data/lib/antelope/ace/grammar/symbols.rb +66 -66
  28. data/lib/antelope/ace/grammar.rb +69 -69
  29. data/lib/antelope/ace/precedence.rb +61 -61
  30. data/lib/antelope/ace/production.rb +57 -57
  31. data/lib/antelope/ace/scanner/argument.rb +57 -57
  32. data/lib/antelope/ace/scanner/first.rb +89 -89
  33. data/lib/antelope/ace/scanner/second.rb +177 -177
  34. data/lib/antelope/ace/scanner/third.rb +27 -27
  35. data/lib/antelope/ace/scanner.rb +134 -134
  36. data/lib/antelope/ace/token/epsilon.rb +24 -24
  37. data/lib/antelope/ace/token/error.rb +26 -26
  38. data/lib/antelope/ace/token/nonterminal.rb +17 -17
  39. data/lib/antelope/ace/token/terminal.rb +17 -17
  40. data/lib/antelope/ace/token.rb +238 -238
  41. data/lib/antelope/ace.rb +53 -53
  42. data/lib/antelope/cli.rb +55 -55
  43. data/lib/antelope/errors.rb +8 -8
  44. data/lib/antelope/generation/constructor/first.rb +88 -88
  45. data/lib/antelope/generation/constructor/follow.rb +103 -103
  46. data/lib/antelope/generation/constructor/nullable.rb +64 -64
  47. data/lib/antelope/generation/constructor.rb +126 -126
  48. data/lib/antelope/generation/errors.rb +17 -17
  49. data/lib/antelope/generation/null.rb +13 -13
  50. data/lib/antelope/generation/recognizer/rule.rb +216 -216
  51. data/lib/antelope/generation/recognizer/state.rb +130 -130
  52. data/lib/antelope/generation/recognizer.rb +180 -180
  53. data/lib/antelope/generation/tableizer.rb +175 -154
  54. data/lib/antelope/generation.rb +15 -15
  55. data/lib/antelope/generator/base.rb +264 -264
  56. data/lib/antelope/generator/c.rb +11 -11
  57. data/lib/antelope/generator/c_header.rb +105 -105
  58. data/lib/antelope/generator/c_source.rb +39 -39
  59. data/lib/antelope/generator/error.rb +34 -0
  60. data/lib/antelope/generator/group.rb +57 -57
  61. data/lib/antelope/generator/html.rb +51 -0
  62. data/lib/antelope/generator/info.rb +47 -0
  63. data/lib/antelope/generator/null.rb +18 -18
  64. data/lib/antelope/generator/output.rb +17 -49
  65. data/lib/antelope/generator/ruby.rb +79 -79
  66. data/lib/antelope/generator/templates/c_header.ant +36 -36
  67. data/lib/antelope/generator/templates/c_source.ant +202 -202
  68. data/lib/antelope/generator/templates/error.ant +33 -0
  69. data/lib/antelope/generator/templates/html/antelope.css +1 -0
  70. data/lib/antelope/generator/templates/html/antelope.html +1 -0
  71. data/lib/antelope/generator/templates/html/antelope.js +1 -0
  72. data/lib/antelope/generator/templates/html/css.ant +53 -0
  73. data/lib/antelope/generator/templates/html/html.ant +82 -0
  74. data/lib/antelope/generator/templates/html/js.ant +9 -0
  75. data/lib/antelope/generator/templates/info.ant +53 -0
  76. data/lib/antelope/generator/templates/ruby.ant +178 -146
  77. data/lib/antelope/generator.rb +66 -63
  78. data/lib/antelope/template/compiler.rb +78 -78
  79. data/lib/antelope/template/errors.rb +9 -9
  80. data/lib/antelope/template/scanner.rb +109 -109
  81. data/lib/antelope/template.rb +65 -60
  82. data/lib/antelope/version.rb +6 -6
  83. data/lib/antelope.rb +13 -13
  84. data/optimizations.txt +42 -0
  85. data/spec/antelope/ace/compiler_spec.rb +60 -60
  86. data/spec/antelope/ace/scanner_spec.rb +27 -27
  87. data/spec/antelope/constructor_spec.rb +133 -136
  88. data/spec/antelope/template_spec.rb +50 -49
  89. data/spec/fixtures/simple.ace +22 -22
  90. data/spec/spec_helper.rb +39 -39
  91. data/spec/support/benchmark_helper.rb +5 -5
  92. data/spec/support/grammar_helper.rb +15 -15
  93. data/subl/Ace (Ruby).JSON-tmLanguage +94 -94
  94. data/subl/Ace (Ruby).tmLanguage +153 -153
  95. metadata +17 -6
  96. data/lib/antelope/generator/templates/output.ant +0 -68
@@ -1,154 +1,175 @@
1
- # encoding: utf-8
2
-
3
- module Antelope
4
- module Generation
5
-
6
- # Constructs the table required for the parser.
7
- class Tableizer
8
-
9
- # The grammar that the table is based off of.
10
- #
11
- # @return [Ace::Grammar]
12
- attr_accessor :grammar
13
-
14
- # The table itself.
15
- #
16
- # @return [Array<Hash<(Symbol, Array<(Symbol, Numeric)>)>>]
17
- attr_accessor :table
18
-
19
- # All rules in the grammar.
20
- #
21
- # @return [Hash<(Numeric, Recognizer::Rule)>]
22
- attr_accessor :rules
23
-
24
- attr_reader :conflicts
25
-
26
- # Initialize.
27
- #
28
- # @param grammar [Ace::Grammar]
29
- def initialize(grammar)
30
- @grammar = grammar
31
- end
32
-
33
- # Construct the table, and then check the table for conflicts.
34
- #
35
- # @return [void]
36
- # @see #tablize
37
- # @see #conflictize
38
- def call
39
- tablize
40
- conflictize
41
- defaultize
42
- end
43
-
44
- # Construct a table based on the grammar. The table itself is
45
- # an array whose elements are hashes; the index of the array
46
- # corresponds to the state ID, and the keys of the hashes
47
- # correspond to acceptable tokens. The values of the hashes
48
- # should be an array of arrays (at this point).
49
- #
50
- # @return [void]
51
- def tablize
52
- @table = Array.new(grammar.states.size) do
53
- Hash.new { |h, k| h[k] = [] }
54
- end
55
- @rules = []
56
-
57
- grammar.states.each do |state|
58
- state.transitions.each do |on, to|
59
- table[state.id][on] << [:state, to.id]
60
- end
61
-
62
- state.rules.each do |rule|
63
- @rules[rule.production.id] = rule.production
64
- if rule.final?
65
- rule.lookahead.each do |look|
66
- table[state.id][look.name] <<
67
- [:reduce, rule.production.id]
68
- end
69
-
70
- if rule.production.id.zero?
71
- table[state.id][:$end] =
72
- [[:accept, rule.production.id]]
73
- end
74
- end
75
- end
76
- end
77
-
78
- table
79
- end
80
-
81
- # Resolve any conflicts through precedence, if we can. If we
82
- # can't, let the user know. This makes sure that every value
83
- # of the hashes is a single array.
84
- #
85
- # @raise [UnresolvableConflictError] if a conflict could not be
86
- # resolved using precedence rules.
87
- # @return [void]
88
- def conflictize
89
- @conflicts = Hash.new { |h, k| h[k] = {} }
90
- @table.each_with_index do |v, state|
91
- v.each do |on, data|
92
- if data.size == 1
93
- @table[state][on] = data[0]
94
- next
95
- end
96
-
97
- terminal = grammar.precedence_for(on)
98
-
99
- rule_part, other_part = data.sort_by { |(t, _)| t }
100
-
101
- unless other_part[0] == :state
102
- $stderr.puts \
103
- "Could not determine move for #{on} in state " \
104
- "#{state} (reduce/reduce conflict)"
105
- next
106
- end
107
-
108
- result = @rules[rule_part[1]].prec <=> terminal
109
-
110
- case result
111
- when 0
112
- conflicts[state][on] = [
113
- rule_part, other_part, terminal, @rules[rule_part[1]].prec
114
- ]
115
- $stderr.puts \
116
- "Could not determine move for #{on} in state " \
117
- "#{state} (shift/reduce conflict)"
118
- when 1
119
- @table[state][on] = rule_part
120
- when -1
121
- @table[state][on] = other_part
122
- end
123
- end
124
- end
125
- end
126
-
127
- # Reduce many transitions into a single `$default` transition.
128
- # This only works if there is no `$empty` transition; if there
129
- # is an `$empty` transition, then the `$default` transition is
130
- # set to be the `$empty` transition.
131
- #
132
- # @return [void]
133
- def defaultize
134
- max = @table.map { |s| s.keys.size }.max
135
- @table.each_with_index do |state|
136
- if state.key?(:$empty)
137
- state[:$default] = state[:$empty]
138
- else
139
- common = state.group_by { |k, v| v }.values.
140
- sort_by(&:size).first
141
-
142
- if common.size > (max / 2)
143
- action = common[0][1]
144
-
145
- keys = common.map(&:first)
146
- state.delete_if { |k, _| keys.include?(k) }
147
- state[:$default] = action
148
- end
149
- end
150
- end
151
- end
152
- end
153
- end
154
- end
1
+ # encoding: utf-8
2
+
3
+ module Antelope
4
+ module Generation
5
+
6
+ # Constructs the table required for the parser.
7
+ class Tableizer
8
+
9
+ # The grammar that the table is based off of.
10
+ #
11
+ # @return [Ace::Grammar]
12
+ attr_accessor :grammar
13
+
14
+ # The table itself.
15
+ #
16
+ # @return [Array<Hash<(Symbol, Array<(Symbol, Numeric)>)>>]
17
+ attr_accessor :table
18
+
19
+ # All rules in the grammar.
20
+ #
21
+ # @return [Hash<(Numeric, Recognizer::Rule)>]
22
+ attr_accessor :rules
23
+
24
+ attr_reader :conflicts
25
+
26
+ # Initialize.
27
+ #
28
+ # @param grammar [Ace::Grammar]
29
+ def initialize(grammar)
30
+ @grammar = grammar
31
+ end
32
+
33
+ # Construct the table, and then check the table for conflicts.
34
+ #
35
+ # @return [void]
36
+ # @see #tablize
37
+ # @see #conflictize
38
+ def call
39
+ tablize
40
+ conflictize
41
+ defaultize
42
+ end
43
+
44
+ # Construct a table based on the grammar. The table itself is
45
+ # an array whose elements are hashes; the index of the array
46
+ # corresponds to the state ID, and the keys of the hashes
47
+ # correspond to acceptable tokens. The values of the hashes
48
+ # should be an array of arrays (at this point).
49
+ #
50
+ # @return [void]
51
+ def tablize
52
+ @table = Array.new(grammar.states.size) do
53
+ Hash.new { |h, k| h[k] = [] }
54
+ end
55
+ @rules = []
56
+
57
+ grammar.states.each do |state|
58
+ state.transitions.each do |on, to|
59
+ table[state.id][on] << [:state, to.id]
60
+ end
61
+
62
+ state.rules.each do |rule|
63
+ @rules[rule.production.id] = rule.production
64
+ if rule.final?
65
+ rule.lookahead.each do |look|
66
+ table[state.id][look.name] <<
67
+ [:reduce, rule.production.id]
68
+ end
69
+
70
+ if rule.production.id.zero?
71
+ table[state.id][:$end] =
72
+ [[:accept, rule.production.id]]
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ table
79
+ end
80
+
81
+ # Resolve any conflicts through precedence, if we can. If we
82
+ # can't, let the user know. This makes sure that every value
83
+ # of the hashes is a single array.
84
+ #
85
+ # @raise [UnresolvableConflictError] if a conflict could not be
86
+ # resolved using precedence rules.
87
+ # @return [void]
88
+ def conflictize
89
+ states = grammar.states.to_a.sort_by(&:id)
90
+ @conflicts = Hash.new { |h, k| h[k] = {} }
91
+ @table.each_with_index do |v, state|
92
+ v.each do |on, data|
93
+ if data.size == 1
94
+ @table[state][on] = data[0]
95
+ next
96
+ end
97
+
98
+ terminal = grammar.precedence_for(on)
99
+ rule_part, other_part = data.sort_by { |(t, _)| t }
100
+
101
+ conflict = proc do |result|
102
+ hash = { result: result,
103
+ terminal: terminal,
104
+ prec: @rules[rule_part[1]].prec,
105
+ data: data,
106
+ rules: [], transitions: [] }
107
+
108
+ hash[:rules].concat(data.select { |part|
109
+ part[0] == :reduce || part[0] == :accept
110
+ }.map { |(_, id)|
111
+ states[state].rules.select(&:final?).
112
+ detect { |rule| rule.production.id == id }
113
+ })
114
+ hash[:transitions].concat(data.select { |part|
115
+ part[0] == :state
116
+ }.map { |_|
117
+ states[state].rules.
118
+ detect { |rule| rule.active.name == on }
119
+ })
120
+
121
+ #conflicts[state][on] = [result, rule_part, other_part,
122
+ # terminal, @rules[rule_part[1]].prec]
123
+ conflicts[state][on] = hash
124
+ end
125
+
126
+ unless other_part[0] == :state
127
+ conflict.call(0)
128
+ $stderr.puts \
129
+ "Could not determine move for #{on} in state " \
130
+ "#{state} (reduce/reduce conflict)"
131
+ next
132
+ end
133
+
134
+ result = @rules[rule_part[1]].prec <=> terminal
135
+ conflict.call(result)
136
+
137
+ case result
138
+ when 0
139
+ @table[state][on] = nil
140
+ $stderr.puts \
141
+ "Could not determine move for #{on} in state " \
142
+ "#{state} (shift/reduce conflict)"
143
+ when 1
144
+ @table[state][on] = rule_part
145
+ when -1
146
+ @table[state][on] = other_part
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ # Reduce many transitions into a single `$default` transition.
153
+ # This only works if there is no `$empty` transition; if there
154
+ # is an `$empty` transition, then the `$default` transition is
155
+ # set to be the `$empty` transition.
156
+ #
157
+ # @return [void]
158
+ def defaultize
159
+ max = @table.map { |s| s.keys.size }.max
160
+ @table.each_with_index do |state|
161
+ common = state.group_by { |k, v| v }.values.
162
+ sort_by(&:size).first
163
+
164
+ if common.size > (max / 2)
165
+ action = common[0][1]
166
+
167
+ keys = common.map(&:first)
168
+ state.delete_if { |k, _| keys.include?(k) }
169
+ state[:$default] = action
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -1,15 +1,15 @@
1
- # encoding: utf-8
2
-
3
- require "antelope/generation/errors"
4
- require "antelope/generation/constructor"
5
- require "antelope/generation/recognizer"
6
- require "antelope/generation/tableizer"
7
- require "antelope/generation/null"
8
-
9
- module Antelope
10
-
11
- # Contains the generation mods.
12
- module Generation
13
-
14
- end
15
- end
1
+ # encoding: utf-8
2
+
3
+ require "antelope/generation/errors"
4
+ require "antelope/generation/constructor"
5
+ require "antelope/generation/recognizer"
6
+ require "antelope/generation/tableizer"
7
+ require "antelope/generation/null"
8
+
9
+ module Antelope
10
+
11
+ # Contains the generation mods.
12
+ module Generation
13
+
14
+ end
15
+ end