antelope 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +25 -23
- data/.rspec +3 -3
- data/.travis.yml +10 -9
- data/.yardopts +7 -7
- data/CONTRIBUTING.md +38 -38
- data/GENERATORS.md +124 -124
- data/Gemfile +7 -7
- data/LICENSE.txt +22 -22
- data/README.md +104 -104
- data/Rakefile +2 -2
- data/TODO.md +58 -58
- data/antelope.gemspec +28 -28
- data/bin/antelope +7 -7
- data/examples/deterministic.ace +35 -35
- data/examples/example.ace +51 -50
- data/examples/example.err +192 -0
- data/examples/{example.output → example.inf} +384 -385
- data/examples/liquidscript.ace +233 -162
- data/examples/simple.ace +22 -22
- data/lib/antelope/ace/compiler.rb +334 -334
- data/lib/antelope/ace/errors.rb +48 -48
- data/lib/antelope/ace/grammar/generation.rb +80 -80
- data/lib/antelope/ace/grammar/loading.rb +53 -53
- data/lib/antelope/ace/grammar/precedences.rb +68 -65
- data/lib/antelope/ace/grammar/productions.rb +156 -150
- data/lib/antelope/ace/grammar/symbols.rb +66 -66
- data/lib/antelope/ace/grammar.rb +69 -69
- data/lib/antelope/ace/precedence.rb +61 -61
- data/lib/antelope/ace/production.rb +57 -57
- data/lib/antelope/ace/scanner/argument.rb +57 -57
- data/lib/antelope/ace/scanner/first.rb +89 -89
- data/lib/antelope/ace/scanner/second.rb +177 -177
- data/lib/antelope/ace/scanner/third.rb +27 -27
- data/lib/antelope/ace/scanner.rb +134 -134
- data/lib/antelope/ace/token/epsilon.rb +24 -24
- data/lib/antelope/ace/token/error.rb +26 -26
- data/lib/antelope/ace/token/nonterminal.rb +17 -17
- data/lib/antelope/ace/token/terminal.rb +17 -17
- data/lib/antelope/ace/token.rb +238 -238
- data/lib/antelope/ace.rb +53 -53
- data/lib/antelope/cli.rb +55 -55
- data/lib/antelope/errors.rb +8 -8
- data/lib/antelope/generation/constructor/first.rb +88 -88
- data/lib/antelope/generation/constructor/follow.rb +103 -103
- data/lib/antelope/generation/constructor/nullable.rb +64 -64
- data/lib/antelope/generation/constructor.rb +126 -126
- data/lib/antelope/generation/errors.rb +17 -17
- data/lib/antelope/generation/null.rb +13 -13
- data/lib/antelope/generation/recognizer/rule.rb +216 -216
- data/lib/antelope/generation/recognizer/state.rb +130 -130
- data/lib/antelope/generation/recognizer.rb +180 -180
- data/lib/antelope/generation/tableizer.rb +175 -154
- data/lib/antelope/generation.rb +15 -15
- data/lib/antelope/generator/base.rb +264 -264
- data/lib/antelope/generator/c.rb +11 -11
- data/lib/antelope/generator/c_header.rb +105 -105
- data/lib/antelope/generator/c_source.rb +39 -39
- data/lib/antelope/generator/error.rb +34 -0
- data/lib/antelope/generator/group.rb +57 -57
- data/lib/antelope/generator/html.rb +51 -0
- data/lib/antelope/generator/info.rb +47 -0
- data/lib/antelope/generator/null.rb +18 -18
- data/lib/antelope/generator/output.rb +17 -49
- data/lib/antelope/generator/ruby.rb +79 -79
- data/lib/antelope/generator/templates/c_header.ant +36 -36
- data/lib/antelope/generator/templates/c_source.ant +202 -202
- data/lib/antelope/generator/templates/error.ant +33 -0
- data/lib/antelope/generator/templates/html/antelope.css +1 -0
- data/lib/antelope/generator/templates/html/antelope.html +1 -0
- data/lib/antelope/generator/templates/html/antelope.js +1 -0
- data/lib/antelope/generator/templates/html/css.ant +53 -0
- data/lib/antelope/generator/templates/html/html.ant +82 -0
- data/lib/antelope/generator/templates/html/js.ant +9 -0
- data/lib/antelope/generator/templates/info.ant +53 -0
- data/lib/antelope/generator/templates/ruby.ant +178 -146
- data/lib/antelope/generator.rb +66 -63
- data/lib/antelope/template/compiler.rb +78 -78
- data/lib/antelope/template/errors.rb +9 -9
- data/lib/antelope/template/scanner.rb +109 -109
- data/lib/antelope/template.rb +65 -60
- data/lib/antelope/version.rb +6 -6
- data/lib/antelope.rb +13 -13
- data/optimizations.txt +42 -0
- data/spec/antelope/ace/compiler_spec.rb +60 -60
- data/spec/antelope/ace/scanner_spec.rb +27 -27
- data/spec/antelope/constructor_spec.rb +133 -136
- data/spec/antelope/template_spec.rb +50 -49
- data/spec/fixtures/simple.ace +22 -22
- data/spec/spec_helper.rb +39 -39
- data/spec/support/benchmark_helper.rb +5 -5
- data/spec/support/grammar_helper.rb +15 -15
- data/subl/Ace (Ruby).JSON-tmLanguage +94 -94
- data/subl/Ace (Ruby).tmLanguage +153 -153
- metadata +17 -6
- data/lib/antelope/generator/templates/output.ant +0 -68
@@ -1,216 +1,216 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "securerandom"
|
4
|
-
|
5
|
-
module Antelope
|
6
|
-
module Generation
|
7
|
-
class Recognizer
|
8
|
-
|
9
|
-
# Defines a rule. A rule has a corresponding production, and a
|
10
|
-
# position in that production. It also contains extra
|
11
|
-
# information for other reasons.
|
12
|
-
class Rule
|
13
|
-
|
14
|
-
# The left-hand side of the rule.
|
15
|
-
#
|
16
|
-
# @return [Ace::Token::Nonterminal]
|
17
|
-
attr_reader :left
|
18
|
-
|
19
|
-
# The right-hand side of the rule.
|
20
|
-
#
|
21
|
-
# @return [Array<Ace::Token>]
|
22
|
-
attr_reader :right
|
23
|
-
|
24
|
-
# The current position inside of the rule.
|
25
|
-
#
|
26
|
-
# @return [Numeric]
|
27
|
-
attr_reader :position
|
28
|
-
|
29
|
-
# The block to be executed on production match.
|
30
|
-
#
|
31
|
-
# @deprecated Use {Ace::Production#block} instead.
|
32
|
-
# @return [String]
|
33
|
-
attr_reader :block
|
34
|
-
|
35
|
-
# The lookahead set for this specific rule. Contains nothing
|
36
|
-
# unless {#final?} returns true.
|
37
|
-
#
|
38
|
-
# @return [Set<Symbol>]
|
39
|
-
attr_accessor :lookahead
|
40
|
-
|
41
|
-
# The id for this rule. Initialy, this is set to a string of
|
42
|
-
# hexadecimal characters; after construction of all states,
|
43
|
-
# however, it is a number.
|
44
|
-
#
|
45
|
-
# @return [String, Numeric]
|
46
|
-
attr_accessor :id
|
47
|
-
|
48
|
-
# The precedence for this rule.
|
49
|
-
#
|
50
|
-
# @return [Ace::Precedence]
|
51
|
-
attr_accessor :precedence
|
52
|
-
|
53
|
-
# The associated production.
|
54
|
-
#
|
55
|
-
# @return [Ace::Production]
|
56
|
-
attr_reader :production
|
57
|
-
|
58
|
-
include Comparable
|
59
|
-
|
60
|
-
# Initialize the rule.
|
61
|
-
#
|
62
|
-
# @param production [Ace::Production] the production
|
63
|
-
# that this rule is based off of.
|
64
|
-
# @param position [Numeric] the position that this rule is in
|
65
|
-
# the production.
|
66
|
-
# @param inherited [nil] do not use.
|
67
|
-
def initialize(production, position, inherited = false)
|
68
|
-
@left = production.label.dup
|
69
|
-
@position = position
|
70
|
-
@lookahead = Set.new
|
71
|
-
@precedence = production.prec
|
72
|
-
@production = production
|
73
|
-
@block = production.block
|
74
|
-
@id =
|
75
|
-
|
76
|
-
if inherited
|
77
|
-
@left, @right = inherited
|
78
|
-
else
|
79
|
-
@right = production.items.map(&:dup)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Give a nice representation of the rule as a string.
|
84
|
-
#
|
85
|
-
# @return [String]
|
86
|
-
def inspect
|
87
|
-
"#<#{self.class} id=#{id} left=#{left} " \
|
88
|
-
"right=[#{right.join(" ")}] position=#{position}>"
|
89
|
-
end
|
90
|
-
|
91
|
-
# Give a nicer representation of the rule as a string. Shows
|
92
|
-
# the id of the rule, the precedence, and the actual
|
93
|
-
# production; if the given argument is true, it will show a
|
94
|
-
# dot to show the position of the rule.
|
95
|
-
#
|
96
|
-
# @param dot [Boolean] show the current position of the rule.
|
97
|
-
# @return [String]
|
98
|
-
def to_s(dot = true)
|
99
|
-
"#{id}/#{precedence.type.to_s[0]}#{precedence.level}: " \
|
100
|
-
"#{left} → #{right[0, position].join(" ")}" \
|
101
|
-
"#{" • " if dot}#{right[position..-1].join(" ")}"
|
102
|
-
end
|
103
|
-
|
104
|
-
# Returns the active token. If there is no active token, it
|
105
|
-
# returns a blank {Ace::Token}.
|
106
|
-
#
|
107
|
-
# @return [Ace::Token]
|
108
|
-
def active
|
109
|
-
right[position] or Ace::Token.new(nil)
|
110
|
-
end
|
111
|
-
|
112
|
-
# Creates the rule after this one by incrementing the position
|
113
|
-
# by one. {#succ?} should be called to make sure that this
|
114
|
-
# rule exists.
|
115
|
-
#
|
116
|
-
# @return [Rule]
|
117
|
-
def succ
|
118
|
-
Rule.new(production, position + 1, [left, right])
|
119
|
-
end
|
120
|
-
|
121
|
-
# Checks to see if a rule can exist after this one; i.e. the
|
122
|
-
# position is not equal to the size of the right side of the
|
123
|
-
# rule.
|
124
|
-
#
|
125
|
-
# @return [Boolean]
|
126
|
-
def succ?
|
127
|
-
right.size > position
|
128
|
-
end
|
129
|
-
|
130
|
-
# Checks to see if this is the final rule, as in no rule can
|
131
|
-
# exist after this one; i.e. the position is equal to the
|
132
|
-
# size of the right side.
|
133
|
-
#
|
134
|
-
# @return [Boolean]
|
135
|
-
def final?
|
136
|
-
!succ?
|
137
|
-
end
|
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
|
-
|
148
|
-
# Compares this rule to another object. If the other object
|
149
|
-
# is not a rule, it delegates the comparison. Otherwise, it
|
150
|
-
# converts both this and the other rule into arrays and
|
151
|
-
# compares the result.
|
152
|
-
#
|
153
|
-
# @param other [Object] the object to compare.
|
154
|
-
# @return [Numeric]
|
155
|
-
def <=>(other)
|
156
|
-
if other.is_a? Rule
|
157
|
-
to_a <=> other.to_a
|
158
|
-
else
|
159
|
-
super
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def ==(other)
|
164
|
-
hash == other.hash if other.respond_to?(:hash)
|
165
|
-
end
|
166
|
-
|
167
|
-
alias_method :eql?, :==
|
168
|
-
|
169
|
-
# Fuzzily compares this object to another object. If the
|
170
|
-
# other object is not a rule, it delegates the comparison.
|
171
|
-
# Otherwise, it fuzzily compares the left and right sides.
|
172
|
-
#
|
173
|
-
# @param other [Object] the object to compare.
|
174
|
-
# @return [Numeric]
|
175
|
-
def ===(other)
|
176
|
-
if other.is_a? Rule
|
177
|
-
left === other.left and right.size == other.right.size and
|
178
|
-
right.each_with_index.
|
179
|
-
all? { |e, i| e === other.right[i] }
|
180
|
-
else
|
181
|
-
super
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# Produces a clone of the rule; any modifications made to the
|
186
|
-
# contents of that rule do not reflect the contents of this
|
187
|
-
# rule.
|
188
|
-
#
|
189
|
-
# @return [Rule]
|
190
|
-
def clone
|
191
|
-
Rule.new(production, position)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Generates a hash for this class.
|
195
|
-
#
|
196
|
-
# @note This is not intended for use. It is only defined to be
|
197
|
-
# compatible with Hashs (and by extension, Sets).
|
198
|
-
# @private
|
199
|
-
# @return [Object]
|
200
|
-
def hash
|
201
|
-
@_hash ||= to_a.hash
|
202
|
-
end
|
203
|
-
|
204
|
-
# Creates an array representation of this class.
|
205
|
-
#
|
206
|
-
# @note This is not intended for use. It is only defined to
|
207
|
-
# make equality checking easier, and to create a hash.
|
208
|
-
# @private
|
209
|
-
# @return [Array<(Ace::Token::Nonterminal, Array<Ace::Token>, Numeric)>]
|
210
|
-
def to_a
|
211
|
-
@_array ||= [left, right, position]
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
|
5
|
+
module Antelope
|
6
|
+
module Generation
|
7
|
+
class Recognizer
|
8
|
+
|
9
|
+
# Defines a rule. A rule has a corresponding production, and a
|
10
|
+
# position in that production. It also contains extra
|
11
|
+
# information for other reasons.
|
12
|
+
class Rule
|
13
|
+
|
14
|
+
# The left-hand side of the rule.
|
15
|
+
#
|
16
|
+
# @return [Ace::Token::Nonterminal]
|
17
|
+
attr_reader :left
|
18
|
+
|
19
|
+
# The right-hand side of the rule.
|
20
|
+
#
|
21
|
+
# @return [Array<Ace::Token>]
|
22
|
+
attr_reader :right
|
23
|
+
|
24
|
+
# The current position inside of the rule.
|
25
|
+
#
|
26
|
+
# @return [Numeric]
|
27
|
+
attr_reader :position
|
28
|
+
|
29
|
+
# The block to be executed on production match.
|
30
|
+
#
|
31
|
+
# @deprecated Use {Ace::Production#block} instead.
|
32
|
+
# @return [String]
|
33
|
+
attr_reader :block
|
34
|
+
|
35
|
+
# The lookahead set for this specific rule. Contains nothing
|
36
|
+
# unless {#final?} returns true.
|
37
|
+
#
|
38
|
+
# @return [Set<Symbol>]
|
39
|
+
attr_accessor :lookahead
|
40
|
+
|
41
|
+
# The id for this rule. Initialy, this is set to a string of
|
42
|
+
# hexadecimal characters; after construction of all states,
|
43
|
+
# however, it is a number.
|
44
|
+
#
|
45
|
+
# @return [String, Numeric]
|
46
|
+
attr_accessor :id
|
47
|
+
|
48
|
+
# The precedence for this rule.
|
49
|
+
#
|
50
|
+
# @return [Ace::Precedence]
|
51
|
+
attr_accessor :precedence
|
52
|
+
|
53
|
+
# The associated production.
|
54
|
+
#
|
55
|
+
# @return [Ace::Production]
|
56
|
+
attr_reader :production
|
57
|
+
|
58
|
+
include Comparable
|
59
|
+
|
60
|
+
# Initialize the rule.
|
61
|
+
#
|
62
|
+
# @param production [Ace::Production] the production
|
63
|
+
# that this rule is based off of.
|
64
|
+
# @param position [Numeric] the position that this rule is in
|
65
|
+
# the production.
|
66
|
+
# @param inherited [nil] do not use.
|
67
|
+
def initialize(production, position, inherited = false)
|
68
|
+
@left = production.label.dup
|
69
|
+
@position = position
|
70
|
+
@lookahead = Set.new
|
71
|
+
@precedence = production.prec
|
72
|
+
@production = production
|
73
|
+
@block = production.block
|
74
|
+
@id = "%10x" % object_id
|
75
|
+
|
76
|
+
if inherited
|
77
|
+
@left, @right = inherited
|
78
|
+
else
|
79
|
+
@right = production.items.map(&:dup)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Give a nice representation of the rule as a string.
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
def inspect
|
87
|
+
"#<#{self.class} id=#{id} left=#{left} " \
|
88
|
+
"right=[#{right.join(" ")}] position=#{position}>"
|
89
|
+
end
|
90
|
+
|
91
|
+
# Give a nicer representation of the rule as a string. Shows
|
92
|
+
# the id of the rule, the precedence, and the actual
|
93
|
+
# production; if the given argument is true, it will show a
|
94
|
+
# dot to show the position of the rule.
|
95
|
+
#
|
96
|
+
# @param dot [Boolean] show the current position of the rule.
|
97
|
+
# @return [String]
|
98
|
+
def to_s(dot = true)
|
99
|
+
"#{id}/#{precedence.type.to_s[0]}#{precedence.level}: " \
|
100
|
+
"#{left} → #{right[0, position].join(" ")}" \
|
101
|
+
"#{" • " if dot}#{right[position..-1].join(" ")}"
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the active token. If there is no active token, it
|
105
|
+
# returns a blank {Ace::Token}.
|
106
|
+
#
|
107
|
+
# @return [Ace::Token]
|
108
|
+
def active
|
109
|
+
right[position] or Ace::Token.new(nil)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creates the rule after this one by incrementing the position
|
113
|
+
# by one. {#succ?} should be called to make sure that this
|
114
|
+
# rule exists.
|
115
|
+
#
|
116
|
+
# @return [Rule]
|
117
|
+
def succ
|
118
|
+
Rule.new(production, position + 1, [left, right])
|
119
|
+
end
|
120
|
+
|
121
|
+
# Checks to see if a rule can exist after this one; i.e. the
|
122
|
+
# position is not equal to the size of the right side of the
|
123
|
+
# rule.
|
124
|
+
#
|
125
|
+
# @return [Boolean]
|
126
|
+
def succ?
|
127
|
+
right.size > position
|
128
|
+
end
|
129
|
+
|
130
|
+
# Checks to see if this is the final rule, as in no rule can
|
131
|
+
# exist after this one; i.e. the position is equal to the
|
132
|
+
# size of the right side.
|
133
|
+
#
|
134
|
+
# @return [Boolean]
|
135
|
+
def final?
|
136
|
+
!succ?
|
137
|
+
end
|
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
|
+
|
148
|
+
# Compares this rule to another object. If the other object
|
149
|
+
# is not a rule, it delegates the comparison. Otherwise, it
|
150
|
+
# converts both this and the other rule into arrays and
|
151
|
+
# compares the result.
|
152
|
+
#
|
153
|
+
# @param other [Object] the object to compare.
|
154
|
+
# @return [Numeric]
|
155
|
+
def <=>(other)
|
156
|
+
if other.is_a? Rule
|
157
|
+
to_a <=> other.to_a
|
158
|
+
else
|
159
|
+
super
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def ==(other)
|
164
|
+
hash == other.hash if other.respond_to?(:hash)
|
165
|
+
end
|
166
|
+
|
167
|
+
alias_method :eql?, :==
|
168
|
+
|
169
|
+
# Fuzzily compares this object to another object. If the
|
170
|
+
# other object is not a rule, it delegates the comparison.
|
171
|
+
# Otherwise, it fuzzily compares the left and right sides.
|
172
|
+
#
|
173
|
+
# @param other [Object] the object to compare.
|
174
|
+
# @return [Numeric]
|
175
|
+
def ===(other)
|
176
|
+
if other.is_a? Rule
|
177
|
+
left === other.left and right.size == other.right.size and
|
178
|
+
right.each_with_index.
|
179
|
+
all? { |e, i| e === other.right[i] }
|
180
|
+
else
|
181
|
+
super
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Produces a clone of the rule; any modifications made to the
|
186
|
+
# contents of that rule do not reflect the contents of this
|
187
|
+
# rule.
|
188
|
+
#
|
189
|
+
# @return [Rule]
|
190
|
+
def clone
|
191
|
+
Rule.new(production, position)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Generates a hash for this class.
|
195
|
+
#
|
196
|
+
# @note This is not intended for use. It is only defined to be
|
197
|
+
# compatible with Hashs (and by extension, Sets).
|
198
|
+
# @private
|
199
|
+
# @return [Object]
|
200
|
+
def hash
|
201
|
+
@_hash ||= to_a.hash
|
202
|
+
end
|
203
|
+
|
204
|
+
# Creates an array representation of this class.
|
205
|
+
#
|
206
|
+
# @note This is not intended for use. It is only defined to
|
207
|
+
# make equality checking easier, and to create a hash.
|
208
|
+
# @private
|
209
|
+
# @return [Array<(Ace::Token::Nonterminal, Array<Ace::Token>, Numeric)>]
|
210
|
+
def to_a
|
211
|
+
@_array ||= [left, right, position]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|