antelope 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +3 -0
- data/.yardopts +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/antelope.gemspec +30 -0
- data/bin/antelope +24 -0
- data/examples/deterministic.ace +27 -0
- data/examples/deterministic.output +229 -0
- data/examples/example.ace +45 -0
- data/examples/example.output +610 -0
- data/examples/simple.ace +26 -0
- data/examples/simple.output +194 -0
- data/lib/antelope/ace/compiler.rb +290 -0
- data/lib/antelope/ace/errors.rb +27 -0
- data/lib/antelope/ace/grammar/generation.rb +47 -0
- data/lib/antelope/ace/grammar/loading.rb +51 -0
- data/lib/antelope/ace/grammar/presidence.rb +59 -0
- data/lib/antelope/ace/grammar/production.rb +47 -0
- data/lib/antelope/ace/grammar/productions.rb +119 -0
- data/lib/antelope/ace/grammar/terminals.rb +41 -0
- data/lib/antelope/ace/grammar.rb +59 -0
- data/lib/antelope/ace/presidence.rb +51 -0
- data/lib/antelope/ace/scanner/first.rb +61 -0
- data/lib/antelope/ace/scanner/second.rb +160 -0
- data/lib/antelope/ace/scanner/third.rb +25 -0
- data/lib/antelope/ace/scanner.rb +110 -0
- data/lib/antelope/ace/token/epsilon.rb +22 -0
- data/lib/antelope/ace/token/error.rb +24 -0
- data/lib/antelope/ace/token/nonterminal.rb +15 -0
- data/lib/antelope/ace/token/terminal.rb +15 -0
- data/lib/antelope/ace/token.rb +171 -0
- data/lib/antelope/ace.rb +50 -0
- data/lib/antelope/automaton.rb +36 -0
- data/lib/antelope/generation/conflictor/conflict.rb +7 -0
- data/lib/antelope/generation/conflictor.rb +45 -0
- data/lib/antelope/generation/constructor/first.rb +52 -0
- data/lib/antelope/generation/constructor/follow.rb +46 -0
- data/lib/antelope/generation/constructor/lookahead.rb +42 -0
- data/lib/antelope/generation/constructor/nullable.rb +40 -0
- data/lib/antelope/generation/constructor.rb +81 -0
- data/lib/antelope/generation/recognizer/rule.rb +93 -0
- data/lib/antelope/generation/recognizer/state.rb +56 -0
- data/lib/antelope/generation/recognizer.rb +152 -0
- data/lib/antelope/generation/tableizer.rb +80 -0
- data/lib/antelope/generation.rb +12 -0
- data/lib/antelope/generator/output.rb +30 -0
- data/lib/antelope/generator/ruby.rb +57 -0
- data/lib/antelope/generator/templates/output.erb +49 -0
- data/lib/antelope/generator/templates/ruby.erb +62 -0
- data/lib/antelope/generator.rb +84 -0
- data/lib/antelope/version.rb +4 -0
- data/lib/antelope.rb +9 -0
- data/spec/antelope/ace/compiler_spec.rb +50 -0
- data/spec/antelope/ace/scanner_spec.rb +27 -0
- data/spec/antelope/automaton_spec.rb +29 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/benchmark_helper.rb +5 -0
- metadata +223 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
Productions:
|
2
|
+
0/n0: $start(0) → e(0:1) $
|
3
|
+
1/n1: e(0:1) → l(0:2) "=" r(8:10)
|
4
|
+
2/n1: e(0:1) → r(0:3)
|
5
|
+
3/n1: l(8:2) → IDENT
|
6
|
+
4/n1: l(8:2) → "*" r(5:9)
|
7
|
+
5/n1: r(8:10) → l(0:2)
|
8
|
+
12/n1: r(8:10) → l(5:2)
|
9
|
+
18/n1: r(8:10) → l(8:2)
|
10
|
+
|
11
|
+
Original Productions:
|
12
|
+
e → l "=" r
|
13
|
+
|
14
|
+
e → r
|
15
|
+
|
16
|
+
l → IDENT
|
17
|
+
|
18
|
+
l → "*" r
|
19
|
+
|
20
|
+
r → l
|
21
|
+
|
22
|
+
$start → e $
|
23
|
+
|
24
|
+
|
25
|
+
Conflicts:
|
26
|
+
|
27
|
+
Presidence:
|
28
|
+
--- highest
|
29
|
+
nonassoc 1:
|
30
|
+
{_}
|
31
|
+
nonassoc 0:
|
32
|
+
{$}
|
33
|
+
--- lowest
|
34
|
+
|
35
|
+
Table:
|
36
|
+
{0=>
|
37
|
+
{:e=>[:state, 1],
|
38
|
+
:l=>[:state, 2],
|
39
|
+
:r=>[:state, 3],
|
40
|
+
:IDENT=>[:state, 4],
|
41
|
+
:STAR=>[:state, 5]},
|
42
|
+
1=>{:"$"=>[:state, 7]},
|
43
|
+
2=>{:EQUALS=>[:state, 8], :"$"=>[:reduce, 5]},
|
44
|
+
3=>{:"$"=>[:reduce, 2]},
|
45
|
+
4=>{:EQUALS=>[:reduce, 3], :"$"=>[:reduce, 3]},
|
46
|
+
5=>
|
47
|
+
{:r=>[:state, 9], :l=>[:state, 2], :IDENT=>[:state, 4], :STAR=>[:state, 5]},
|
48
|
+
6=>{:"$"=>[:reduce, 5]},
|
49
|
+
7=>{:"$"=>[:accept, 0]},
|
50
|
+
8=>
|
51
|
+
{:r=>[:state, 10], :l=>[:state, 2], :IDENT=>[:state, 4], :STAR=>[:state, 5]},
|
52
|
+
9=>{:EQUALS=>[:reduce, 4], :"$"=>[:reduce, 4]},
|
53
|
+
10=>{:"$"=>[:reduce, 1]}}
|
54
|
+
|
55
|
+
[#<Antelope::Generation::Recognizer::Rule id=0 left=$start(0) right=[e(0:1) $] position=0>,
|
56
|
+
#<Antelope::Generation::Recognizer::Rule id=1 left=e(0:1) right=[l(0:2) "=" r(8:10)] position=0>,
|
57
|
+
#<Antelope::Generation::Recognizer::Rule id=2 left=e(0:1) right=[r(0:3)] position=0>,
|
58
|
+
#<Antelope::Generation::Recognizer::Rule id=3 left=l(8:2) right=[IDENT] position=0>,
|
59
|
+
#<Antelope::Generation::Recognizer::Rule id=4 left=l(8:2) right=["*" r(5:9)] position=0>,
|
60
|
+
#<Antelope::Generation::Recognizer::Rule id=5 left=r(8:10) right=[l(0:2)] position=0>,
|
61
|
+
#<Antelope::Generation::Recognizer::Rule id=6 left=$start(0) right=[e $] position=1>,
|
62
|
+
#<Antelope::Generation::Recognizer::Rule id=7 left=e(0:1) right=[l "=" r] position=1>,
|
63
|
+
nil,
|
64
|
+
#<Antelope::Generation::Recognizer::Rule id=9 left=e(0:1) right=[r] position=1>,
|
65
|
+
#<Antelope::Generation::Recognizer::Rule id=10 left=l(8:2) right=[IDENT] position=1>,
|
66
|
+
#<Antelope::Generation::Recognizer::Rule id=11 left=l(8:2) right=["*" r] position=1>,
|
67
|
+
#<Antelope::Generation::Recognizer::Rule id=12 left=r(8:10) right=[l(5:2)] position=0>,
|
68
|
+
#<Antelope::Generation::Recognizer::Rule id=13 left=l(8:2) right=[IDENT] position=0>,
|
69
|
+
#<Antelope::Generation::Recognizer::Rule id=14 left=l(8:2) right=["*" r(5:9)] position=0>,
|
70
|
+
#<Antelope::Generation::Recognizer::Rule id=15 left=r(8:10) right=[l] position=1>,
|
71
|
+
#<Antelope::Generation::Recognizer::Rule id=16 left=$start(0) right=[e $] position=2>,
|
72
|
+
#<Antelope::Generation::Recognizer::Rule id=17 left=e(0:1) right=[l "=" r] position=2>,
|
73
|
+
#<Antelope::Generation::Recognizer::Rule id=18 left=r(8:10) right=[l(8:2)] position=0>,
|
74
|
+
#<Antelope::Generation::Recognizer::Rule id=19 left=l(8:2) right=[IDENT] position=0>,
|
75
|
+
#<Antelope::Generation::Recognizer::Rule id=20 left=l(8:2) right=["*" r(5:9)] position=0>,
|
76
|
+
#<Antelope::Generation::Recognizer::Rule id=21 left=l(8:2) right=["*" r] position=2>,
|
77
|
+
#<Antelope::Generation::Recognizer::Rule id=22 left=e(0:1) right=[l "=" r] position=3>]
|
78
|
+
|
79
|
+
State 0:
|
80
|
+
rules:
|
81
|
+
0/n0: $start(0) → • e(0:1) $
|
82
|
+
{}
|
83
|
+
1/n1: e(0:1) → • l(0:2) "=" r(8:10)
|
84
|
+
{}
|
85
|
+
2/n1: e(0:1) → • r(0:3)
|
86
|
+
{}
|
87
|
+
3/n1: l(8:2) → • IDENT
|
88
|
+
{}
|
89
|
+
4/n1: l(8:2) → • "*" r(5:9)
|
90
|
+
{}
|
91
|
+
5/n1: r(8:10) → • l(0:2)
|
92
|
+
{}
|
93
|
+
|
94
|
+
transitions:
|
95
|
+
e : State 1
|
96
|
+
l : State 2
|
97
|
+
r : State 3
|
98
|
+
IDENT: State 4
|
99
|
+
STAR : State 5
|
100
|
+
|
101
|
+
State 1:
|
102
|
+
rules:
|
103
|
+
6/n0: $start(0) → e • $
|
104
|
+
{}
|
105
|
+
|
106
|
+
transitions:
|
107
|
+
$: State 7
|
108
|
+
|
109
|
+
State 2:
|
110
|
+
rules:
|
111
|
+
7/n1: e(0:1) → l • "=" r
|
112
|
+
{}
|
113
|
+
15/n1: r(8:10) → l •
|
114
|
+
{$}
|
115
|
+
|
116
|
+
transitions:
|
117
|
+
EQUALS: State 8
|
118
|
+
|
119
|
+
State 3:
|
120
|
+
rules:
|
121
|
+
9/n1: e(0:1) → r •
|
122
|
+
{$}
|
123
|
+
|
124
|
+
transitions:
|
125
|
+
|
126
|
+
State 4:
|
127
|
+
rules:
|
128
|
+
10/n1: l(8:2) → IDENT •
|
129
|
+
{"=", $}
|
130
|
+
|
131
|
+
transitions:
|
132
|
+
|
133
|
+
State 5:
|
134
|
+
rules:
|
135
|
+
11/n1: l(8:2) → "*" • r
|
136
|
+
{}
|
137
|
+
12/n1: r(8:10) → • l(5:2)
|
138
|
+
{}
|
139
|
+
13/n1: l(8:2) → • IDENT
|
140
|
+
{}
|
141
|
+
14/n1: l(8:2) → • "*" r(5:9)
|
142
|
+
{}
|
143
|
+
|
144
|
+
transitions:
|
145
|
+
r : State 9
|
146
|
+
l : State 2
|
147
|
+
IDENT: State 4
|
148
|
+
STAR : State 5
|
149
|
+
|
150
|
+
State 6:
|
151
|
+
rules:
|
152
|
+
15/n1: r(8:10) → l •
|
153
|
+
{$}
|
154
|
+
|
155
|
+
transitions:
|
156
|
+
|
157
|
+
State 7:
|
158
|
+
rules:
|
159
|
+
16/n0: $start(0) → e $ •
|
160
|
+
{}
|
161
|
+
|
162
|
+
transitions:
|
163
|
+
|
164
|
+
State 8:
|
165
|
+
rules:
|
166
|
+
17/n1: e(0:1) → l "=" • r
|
167
|
+
{}
|
168
|
+
18/n1: r(8:10) → • l(8:2)
|
169
|
+
{}
|
170
|
+
19/n1: l(8:2) → • IDENT
|
171
|
+
{}
|
172
|
+
20/n1: l(8:2) → • "*" r(5:9)
|
173
|
+
{}
|
174
|
+
|
175
|
+
transitions:
|
176
|
+
r : State 10
|
177
|
+
l : State 2
|
178
|
+
IDENT: State 4
|
179
|
+
STAR : State 5
|
180
|
+
|
181
|
+
State 9:
|
182
|
+
rules:
|
183
|
+
21/n1: l(8:2) → "*" r •
|
184
|
+
{"=", $}
|
185
|
+
|
186
|
+
transitions:
|
187
|
+
|
188
|
+
State 10:
|
189
|
+
rules:
|
190
|
+
22/n1: e(0:1) → l "=" r •
|
191
|
+
{$}
|
192
|
+
|
193
|
+
transitions:
|
194
|
+
|
@@ -0,0 +1,290 @@
|
|
1
|
+
require "rubygems/requirement"
|
2
|
+
|
3
|
+
module Antelope
|
4
|
+
module Ace
|
5
|
+
|
6
|
+
# Compiles a set of tokens generated by {Scanner}. These tokens
|
7
|
+
# may not nessicarily have been generated by {Scanner}, however
|
8
|
+
# the tokens must follow the same rules even still.
|
9
|
+
#
|
10
|
+
# A list of all tokens that this compiler accepts:
|
11
|
+
#
|
12
|
+
# - `:directive` (2 arguments)
|
13
|
+
# - `:copy` (1 argument)
|
14
|
+
# - `:second` (no arguments)
|
15
|
+
# - `:label` (1 argument)
|
16
|
+
# - `:part` (1 argument)
|
17
|
+
# - `:or` (no arguments)
|
18
|
+
# - `:prec` (1 argument)
|
19
|
+
# - `:block` (1 argument)
|
20
|
+
# - `:third` (no arguments)
|
21
|
+
# - `:body` (1 argument)
|
22
|
+
#
|
23
|
+
# The tokens are handled by methods that follow the rule
|
24
|
+
# `compile_<token name>`.
|
25
|
+
class Compiler
|
26
|
+
|
27
|
+
# The body of the output compiler. This should be formatted in
|
28
|
+
# the language that the parser is to be written in. Some output
|
29
|
+
# generators may have special syntax that allows the parser to
|
30
|
+
# be put in the body; see the output generators for more.
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
attr_accessor :body
|
34
|
+
|
35
|
+
# A list of all the rules that are defined in the file. The
|
36
|
+
# rules are defined as such:
|
37
|
+
#
|
38
|
+
# - **`label`** (`Symbol`) — The left-hand side of the rule;
|
39
|
+
# this is the nonterminal that the right side reduces to.
|
40
|
+
# - **`set`** (`Array<Symbol>`) — The right-hand side of the
|
41
|
+
# rule. This is a combination of terminals and nonterminals.
|
42
|
+
# - **`block`** (`String`) — The code to be run on a reduction.
|
43
|
+
# this should be formatted in the language that the output
|
44
|
+
# parser is written in. Optional; default value is `""`.
|
45
|
+
# - **`prec`** (`String`) — The presidence level for the
|
46
|
+
# rule. This should be a nonterminal or terminal. Optional;
|
47
|
+
# default value is `""`.
|
48
|
+
#
|
49
|
+
# @return [Array<Hash>]
|
50
|
+
attr_accessor :rules
|
51
|
+
|
52
|
+
# Options defined by directives in the first part of the file.
|
53
|
+
#
|
54
|
+
# - **`:terminals`** (`Array<Symbol, String?)>)` — A list
|
55
|
+
# of all of the terminals in the language. If this is not
|
56
|
+
# properly defined, the grammar will throw an error saying
|
57
|
+
# that a symbol used in the grammar is not defined.
|
58
|
+
# - **`:prec`** (`Array<(Symbol, Array<Symbol>)>`) — A list
|
59
|
+
# of the presidence rules of the grammar. The first element
|
60
|
+
# of each element is the _type_ of presidence (and should be
|
61
|
+
# any of `:left`, `:right`, or `:nonassoc`), and the second
|
62
|
+
# element should be the symbols that are on that level.
|
63
|
+
# - **`:type`** (`String`) — The type of generator to
|
64
|
+
# generate; this should be a language. It's currently
|
65
|
+
# ineffective.
|
66
|
+
# - **`:extra`** (`Hash<Symbol, Array<Object>>`) — Extra
|
67
|
+
# options that are not defined here.
|
68
|
+
# @return [Hash]
|
69
|
+
attr_accessor :options
|
70
|
+
|
71
|
+
# Creates a compiler, and then runs the compiler.
|
72
|
+
#
|
73
|
+
# @param (see #initialize)
|
74
|
+
# @see #compile
|
75
|
+
# @return [Compiler] the compiler.
|
76
|
+
def self.compile(tokens)
|
77
|
+
new(tokens).compile
|
78
|
+
end
|
79
|
+
|
80
|
+
# Initialize the compiler. The compiler keeps track of a state;
|
81
|
+
# this state is basically which part of the file we're in. The
|
82
|
+
# state can be `:first`, `:second`, or `:third`; some tokens
|
83
|
+
# may not exist in certain states.
|
84
|
+
#
|
85
|
+
# @param tokens [Array<Array<(Symbol, Object, ...)>>] the tokens
|
86
|
+
# from the {Scanner}.
|
87
|
+
def initialize(tokens)
|
88
|
+
@tokens = tokens
|
89
|
+
@body = ""
|
90
|
+
@state = :first
|
91
|
+
@rules = []
|
92
|
+
@current = nil
|
93
|
+
@current_label = nil
|
94
|
+
@options = { :terminals => [], :prec => [], :extra => {} }
|
95
|
+
end
|
96
|
+
|
97
|
+
# Runs the compiler on the input tokens. For each token,
|
98
|
+
# it calls `compile_<type>` with `<type>` being the first
|
99
|
+
# element of the token, with the remaining part of the array
|
100
|
+
# passed as arguments.
|
101
|
+
#
|
102
|
+
# @return [self]
|
103
|
+
def compile
|
104
|
+
@tokens.each do |token|
|
105
|
+
send(:"compile_#{token[0]}", *token[1..-1])
|
106
|
+
end
|
107
|
+
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
# Compiles a directive. This may only be triggered in the first
|
112
|
+
# section of the file. The directive accepts two arguments. The
|
113
|
+
# directive name can be any of the following:
|
114
|
+
#
|
115
|
+
# - `:terminal` — adds a terminal. Requires 1-2
|
116
|
+
# arguments; the first argument is the terminal name, and the
|
117
|
+
# second argument is a string that can represent the terminal.
|
118
|
+
# - `:require` — requires a certain version of Antelope.
|
119
|
+
# Requires 1 argument. If the first argument is a version
|
120
|
+
# greater than the current version of Antelope, it raises
|
121
|
+
# an error.
|
122
|
+
# - `:left` — creates a new presidence level, with the
|
123
|
+
# argument values being the symbols. The presidence level
|
124
|
+
# is left associative.
|
125
|
+
# - `:right` — creates a new presidence level, with the
|
126
|
+
# argument valeus being the symbols. The presidence level
|
127
|
+
# is right associative.
|
128
|
+
# - `:nonassoc` — creates a nre presidence level, with the
|
129
|
+
# argument values being the symbols. The presidence level
|
130
|
+
# is nonassociative.
|
131
|
+
# - `:type` — the type of parser to generate. This should
|
132
|
+
# correspond to the output language of the parser. Currently
|
133
|
+
# ineffective.
|
134
|
+
#
|
135
|
+
# @param name [String, Symbol] the name of the directive.
|
136
|
+
# Accepts any of `:terminal`, `:require`, `:left`, `:right`,
|
137
|
+
# `:nonassoc`, and `:type`. Any other values produce an
|
138
|
+
# error on stderr and are put in the `:extra` hash on
|
139
|
+
# {#options}.
|
140
|
+
# @param args [Array<String>] the arguments to the directive.
|
141
|
+
# @return [void]
|
142
|
+
# @see #options
|
143
|
+
def compile_directive(name, args)
|
144
|
+
require_state! :first
|
145
|
+
name = name.intern
|
146
|
+
case name
|
147
|
+
when :terminal
|
148
|
+
@options[:terminals] << [args[0].intern, args[1]]
|
149
|
+
when :require
|
150
|
+
compare_versions(args[0])
|
151
|
+
when :left, :right, :nonassoc
|
152
|
+
@options[:prec] << [name, *args.map(&:intern)]
|
153
|
+
when :type
|
154
|
+
@options[:type] = args[0]
|
155
|
+
else
|
156
|
+
@options[:extra][name] = args
|
157
|
+
$stderr.puts "Unknown Directive: #{name}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Compiles a copy token. A copy token basically copies its
|
162
|
+
# argument directly into the body. Used in both the first
|
163
|
+
# and third parts.
|
164
|
+
#
|
165
|
+
# @param body [String] the string to copy into the body.
|
166
|
+
# @return [void]
|
167
|
+
def compile_copy(body)
|
168
|
+
require_state! :first, :third
|
169
|
+
@body << body
|
170
|
+
end
|
171
|
+
|
172
|
+
# Sets the state to the second part.
|
173
|
+
#
|
174
|
+
# @return [void]
|
175
|
+
def compile_second
|
176
|
+
@state = :second
|
177
|
+
end
|
178
|
+
|
179
|
+
# Compiles a label. This starts a rule definition. The token
|
180
|
+
# should only exist in the second part. A rule definition
|
181
|
+
# occurs by setting the `@current_label` to the first argument,
|
182
|
+
# and `@current` to a blank rule save the label set. If a
|
183
|
+
# rule definition was already in progress, it is completed.
|
184
|
+
#
|
185
|
+
# @param label [String] the left-hand side of the rule; it
|
186
|
+
# should be a nonterminal.
|
187
|
+
# @return [void]
|
188
|
+
def compile_label(label)
|
189
|
+
require_state! :second
|
190
|
+
if @current
|
191
|
+
@rules << @current
|
192
|
+
end
|
193
|
+
|
194
|
+
@current_label = label.intern
|
195
|
+
|
196
|
+
@current = {
|
197
|
+
label: @current_label,
|
198
|
+
set: [],
|
199
|
+
block: "",
|
200
|
+
prec: ""
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
# Compiles a part. This should only occur during a rule
|
205
|
+
# definition. The token should only exist in the second part.
|
206
|
+
# It adds the first argument to the set of the current rule.
|
207
|
+
#
|
208
|
+
# @param text [String] the symbol to append to the current rule.
|
209
|
+
def compile_part(text)
|
210
|
+
require_state! :second
|
211
|
+
@current[:set] << text.intern
|
212
|
+
end
|
213
|
+
|
214
|
+
# Compiles an or. This should only occur in a rule definition,
|
215
|
+
# and in the second part. It starts a new rule definition by
|
216
|
+
# calling {#compile_label} with the current label.
|
217
|
+
#
|
218
|
+
# @return [void]
|
219
|
+
# @see #compile_label
|
220
|
+
def compile_or
|
221
|
+
compile_label(@current_label)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Compiles the presidence operator. This should only occur in a
|
225
|
+
# rule definition, and in the second part. It sets the
|
226
|
+
# presidence definition on the current rule.
|
227
|
+
#
|
228
|
+
# @param prec [String] the presidence of the rule.
|
229
|
+
# @return [void]
|
230
|
+
def compile_prec(prec)
|
231
|
+
require_state! :second
|
232
|
+
@current[:prec] = prec
|
233
|
+
end
|
234
|
+
|
235
|
+
# Compiles a block. This should only occur in a rule
|
236
|
+
# definition, and in the second part. It sets the block on the
|
237
|
+
# current rule.
|
238
|
+
#
|
239
|
+
# @param block [String] the block.
|
240
|
+
# @return [void]
|
241
|
+
def compile_block(block)
|
242
|
+
require_state! :second
|
243
|
+
@current[:block] = block
|
244
|
+
end
|
245
|
+
|
246
|
+
# Sets the state to the third part. If a rule definition was
|
247
|
+
# in progress, it finishes the rule.
|
248
|
+
#
|
249
|
+
# @return [void]
|
250
|
+
def compile_third
|
251
|
+
if @current
|
252
|
+
@rules << @current
|
253
|
+
@current_label = @current = nil
|
254
|
+
end
|
255
|
+
|
256
|
+
@state = :third
|
257
|
+
end
|
258
|
+
|
259
|
+
private
|
260
|
+
|
261
|
+
# Checks the current state against the given states.
|
262
|
+
#
|
263
|
+
# @raise [InvalidStateError] if none of the given states match
|
264
|
+
# the current state.
|
265
|
+
# @return [void]
|
266
|
+
def require_state!(*state)
|
267
|
+
raise InvalidStateError,
|
268
|
+
"In state #{@state}, " \
|
269
|
+
"required state #{state.join(", ")}" \
|
270
|
+
unless state.include?(@state)
|
271
|
+
end
|
272
|
+
|
273
|
+
# Compares the required version and the Antelope version.
|
274
|
+
#
|
275
|
+
# @raise [IncompatibleVersionError] if the Antelope version
|
276
|
+
# doesn't meet the requirement.
|
277
|
+
# @return [void]
|
278
|
+
def compare_versions(required)
|
279
|
+
antelope_version = Gem::Version.new(Antelope::VERSION)
|
280
|
+
required_version = Gem::Requirement.new(required)
|
281
|
+
|
282
|
+
unless required_version =~ antelope_version
|
283
|
+
raise IncompatibleVersionError,
|
284
|
+
"Grammar requires #{args[0]}, " \
|
285
|
+
"have #{Antelope::VERSION}"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Antelope
|
2
|
+
module Ace
|
3
|
+
|
4
|
+
# Defines an error that can occur within the Ace module. All
|
5
|
+
# errors that are raised within the Ace module are subclasses of
|
6
|
+
# this.
|
7
|
+
class Error < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Used primarily in the {Scanner}, this is raised when an input
|
11
|
+
# is malformed. The message should contain a snippet of the input
|
12
|
+
# which caused the error.
|
13
|
+
class SyntaxError < Error
|
14
|
+
end
|
15
|
+
|
16
|
+
# This is used primarily in the {Grammar}; if a rule references a
|
17
|
+
# token (a nonterminal or a terminal) that was not previously
|
18
|
+
# defined, this is raised.
|
19
|
+
class UndefinedTokenError < Error
|
20
|
+
end
|
21
|
+
|
22
|
+
# Pimarily used in the {Compiler}, if a scanner token appears that
|
23
|
+
# should not be in the current state, this is raised.
|
24
|
+
class InvalidStateError < Error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Antelope
|
2
|
+
module Ace
|
3
|
+
class Grammar
|
4
|
+
|
5
|
+
# The default modifiers for generation. It's not really
|
6
|
+
# recommended to (heh) modify this; however, adding your own
|
7
|
+
# modifier is always acceptable.
|
8
|
+
DEFAULT_MODIFIERS = [
|
9
|
+
[:recognizer, Generation::Recognizer ],
|
10
|
+
[:constructor, Generation::Constructor],
|
11
|
+
[:conflictor, Generation::Conflictor ],
|
12
|
+
[:tableizer, Generation::Tableizer ]
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
# The (as of right now) default generators. Later on, the
|
16
|
+
# grammar will guess which generators are needed for the
|
17
|
+
# specific ace file.
|
18
|
+
DEFAULT_GENERATORS = [Generator::Output, Generator::Ruby].freeze
|
19
|
+
|
20
|
+
# Handles the generation of output for the grammar.
|
21
|
+
module Generation
|
22
|
+
|
23
|
+
# Generates the output. First, it runs through every given
|
24
|
+
# modifier, and instintates it. It then calls every modifier,
|
25
|
+
# turns it into a hash, and passes that hash to each of the
|
26
|
+
# given generators.
|
27
|
+
#
|
28
|
+
# @param generators [Array<Generator>] a list of generators
|
29
|
+
# to use in generation.
|
30
|
+
# @param modifiers [Array<Array<(Symbol, #call)>>] a list of
|
31
|
+
# modifiers to apply to the grammar.
|
32
|
+
# @return [void]
|
33
|
+
def generate(generators = DEFAULT_GENERATORS,
|
34
|
+
modifiers = DEFAULT_MODIFIERS)
|
35
|
+
mods = modifiers.map(&:last).
|
36
|
+
map { |x| x.new(self) }
|
37
|
+
mods.map(&:call)
|
38
|
+
hash = Hash[modifiers.map(&:first).zip(mods)]
|
39
|
+
# This is when we'd generate
|
40
|
+
generators.each do |gen|
|
41
|
+
gen.new(self, hash).generate
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Antelope
|
2
|
+
module Ace
|
3
|
+
class Grammar
|
4
|
+
|
5
|
+
# Handles loading to and from files and strings.
|
6
|
+
module Loading
|
7
|
+
|
8
|
+
# Defines class methods on the grammar.
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
# Loads a grammar from a file. Assumes the output
|
12
|
+
# directory and name from the file name.
|
13
|
+
#
|
14
|
+
# @param file_name [String] the file name.
|
15
|
+
# @return [Grammar]
|
16
|
+
# @see #from_string
|
17
|
+
def from_file(file_name)
|
18
|
+
body = File.read(file_name)
|
19
|
+
output = File.dirname(file_name)
|
20
|
+
name = File.basename(file_name).gsub(/\.[A-Za-z]+/, "")
|
21
|
+
from_string(name, output, body)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Loads a grammar from a string. First runs the scanner and
|
25
|
+
# compiler over the string, and then instantiates a new
|
26
|
+
# Grammar from the resultant.
|
27
|
+
#
|
28
|
+
# @param name [String] the name of the grammar.
|
29
|
+
# @param output [String] the output directory.
|
30
|
+
# @param string [String] the grammar body.
|
31
|
+
# @return [Grammar]
|
32
|
+
# @see Ace::Scanner
|
33
|
+
# @see Ace::Compiler
|
34
|
+
def from_string(name, output, string)
|
35
|
+
scanner = Ace::Scanner.scan(string)
|
36
|
+
compiler = Ace::Compiler.compile(scanner)
|
37
|
+
new(name, output, compiler)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Extends the grammar with the class methods.
|
42
|
+
#
|
43
|
+
# @param receiver [Grammar]
|
44
|
+
# @see ClassMethods
|
45
|
+
def self.included(receiver)
|
46
|
+
receiver.extend ClassMethods
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module Antelope
|
4
|
+
module Ace
|
5
|
+
class Grammar
|
6
|
+
|
7
|
+
# Manages presidence for tokens.
|
8
|
+
module Presidence
|
9
|
+
|
10
|
+
# Accesses the generated presidence list. Lazily generates
|
11
|
+
# the presidence rules on the go, and then caches it.
|
12
|
+
#
|
13
|
+
# @return [Array<Ace::Presidence>]
|
14
|
+
def presidence
|
15
|
+
@_presidence ||= generate_presidence
|
16
|
+
end
|
17
|
+
|
18
|
+
# Finds a presidence rule for a given token. If no direct
|
19
|
+
# rule is defined for that token, it will check for a rule
|
20
|
+
# defined for the special symbol, `:_`. By default, there
|
21
|
+
# is always a rule defined for `:_`.
|
22
|
+
#
|
23
|
+
# @param token [Ace::Token, Symbol]
|
24
|
+
# @return [Ace::Presidence]
|
25
|
+
def presidence_for(token)
|
26
|
+
token = token.name if token.is_a?(Token)
|
27
|
+
|
28
|
+
set = Set.new([token, :_])
|
29
|
+
|
30
|
+
presidence.
|
31
|
+
select { |pr| set.intersect?(pr.tokens) }.
|
32
|
+
first
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Generates the presidence rules. Loops through the compiler
|
38
|
+
# given presidence settings, and then adds two default
|
39
|
+
# presidence rules; one for `:$` (level 0, nonassoc), and one
|
40
|
+
# for `:_` (level 1, nonassoc).
|
41
|
+
#
|
42
|
+
# @return [Array<Ace::Presidence>]
|
43
|
+
def generate_presidence
|
44
|
+
size = @compiler.options[:prec].size + 1
|
45
|
+
presidence = @compiler.options[:prec].
|
46
|
+
each_with_index.map do |prec, i|
|
47
|
+
Ace::Presidence.new(prec[0], prec[1..-1].to_set, size - i)
|
48
|
+
end
|
49
|
+
|
50
|
+
presidence <<
|
51
|
+
Ace::Presidence.new(:nonassoc, [:"$"].to_set, 0) <<
|
52
|
+
Ace::Presidence.new(:nonassoc, [:_].to_set, 1)
|
53
|
+
presidence.sort_by { |_| _.level }.reverse
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|