antelope 0.2.4 → 0.3.0
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/.rubocop.yml +11 -0
- data/bin/antelope +3 -3
- data/examples/{example.err → example.ace.err} +9 -9
- data/examples/{example.inf → example.ace.inf} +57 -9
- data/examples/example.ate +70 -0
- data/examples/example.ate.err +192 -0
- data/examples/example.ate.inf +432 -0
- data/lib/antelope/ace/compiler.rb +4 -4
- data/lib/antelope/ace/errors.rb +0 -18
- data/lib/antelope/ace.rb +6 -12
- data/lib/antelope/cli.rb +1 -1
- data/lib/antelope/dsl/compiler.rb +117 -0
- data/lib/antelope/dsl/contexts/base.rb +29 -0
- data/lib/antelope/dsl/contexts/main.rb +63 -0
- data/lib/antelope/dsl/contexts/match.rb +24 -0
- data/lib/antelope/dsl/contexts/precedence.rb +20 -0
- data/lib/antelope/dsl/contexts/production.rb +24 -0
- data/lib/antelope/dsl/contexts/terminal.rb +28 -0
- data/lib/antelope/dsl/contexts.rb +16 -0
- data/lib/antelope/dsl.rb +9 -0
- data/lib/antelope/errors.rb +18 -1
- data/lib/antelope/generation/constructor/first.rb +10 -12
- data/lib/antelope/generation/constructor/follow.rb +6 -6
- data/lib/antelope/generation/constructor/nullable.rb +6 -6
- data/lib/antelope/generation/constructor.rb +4 -4
- data/lib/antelope/generation/recognizer/rule.rb +17 -17
- data/lib/antelope/generation/recognizer/state.rb +9 -10
- data/lib/antelope/generation/recognizer.rb +8 -11
- data/lib/antelope/generation/tableizer.rb +2 -2
- data/lib/antelope/generator/base.rb +7 -7
- data/lib/antelope/generator/ruby.rb +1 -1
- data/lib/antelope/grammar/generation.rb +77 -0
- data/lib/antelope/grammar/loading.rb +84 -0
- data/lib/antelope/{ace → grammar}/precedence.rb +2 -4
- data/lib/antelope/grammar/precedences.rb +64 -0
- data/lib/antelope/{ace → grammar}/production.rb +11 -12
- data/lib/antelope/grammar/productions.rb +154 -0
- data/lib/antelope/grammar/symbols.rb +64 -0
- data/lib/antelope/{ace → grammar}/token/epsilon.rb +1 -2
- data/lib/antelope/{ace → grammar}/token/error.rb +1 -3
- data/lib/antelope/{ace → grammar}/token/nonterminal.rb +1 -3
- data/lib/antelope/{ace → grammar}/token/terminal.rb +1 -3
- data/lib/antelope/{ace → grammar}/token.rb +12 -15
- data/lib/antelope/grammar.rb +68 -0
- data/lib/antelope/version.rb +1 -1
- data/lib/antelope.rb +12 -6
- data/spec/antelope/ace/compiler_spec.rb +6 -6
- data/spec/antelope/ace/scanner_spec.rb +7 -7
- data/spec/antelope/generation/constructor_spec.rb +131 -0
- data/spec/support/grammar_helper.rb +2 -3
- metadata +32 -19
- data/lib/antelope/ace/grammar/generation.rb +0 -80
- data/lib/antelope/ace/grammar/loading.rb +0 -53
- data/lib/antelope/ace/grammar/precedences.rb +0 -68
- data/lib/antelope/ace/grammar/productions.rb +0 -156
- data/lib/antelope/ace/grammar/symbols.rb +0 -66
- data/lib/antelope/ace/grammar.rb +0 -69
- data/spec/antelope/constructor_spec.rb +0 -133
data/lib/antelope.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
3
|
+
require 'antelope/errors'
|
4
|
+
require 'antelope/generation'
|
5
|
+
require 'antelope/generator'
|
6
|
+
require 'antelope/version'
|
7
|
+
require 'antelope/grammar'
|
8
|
+
require 'antelope/ace'
|
9
|
+
require 'antelope/dsl'
|
10
|
+
require 'antelope/template'
|
9
11
|
|
10
12
|
# Antelope, the compiler compiler.
|
11
13
|
module Antelope
|
14
|
+
def self.define(name, options = {}, &block)
|
15
|
+
@grammar = [name, options, block]
|
16
|
+
end
|
12
17
|
|
18
|
+
class << self; attr_reader :grammar; end
|
13
19
|
end
|
@@ -43,18 +43,18 @@ describe Ace::Compiler do
|
|
43
43
|
its(:body) { should =~ /hello/ }
|
44
44
|
its(:options) { should have_key :type }
|
45
45
|
|
46
|
-
it
|
46
|
+
it 'has the proper terminals' do
|
47
47
|
expect(subject.options[:terminals].map(&:first)).to eq [:NUMBER,
|
48
48
|
:SEMICOLON, :ADD, :LPAREN, :RPAREN]
|
49
49
|
end
|
50
50
|
|
51
|
-
context
|
52
|
-
let
|
51
|
+
context 'with an unmatched version' do
|
52
|
+
let(:file) { "%require \"0.0.0\"\n%%\n%%\n" }
|
53
53
|
|
54
|
-
it
|
55
|
-
expect
|
54
|
+
it 'raises an error' do
|
55
|
+
expect do
|
56
56
|
subject
|
57
|
-
|
57
|
+
end.to raise_error(IncompatibleVersionError)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
describe Ace::Scanner do
|
2
2
|
|
3
|
-
it
|
3
|
+
it 'properly scans' do
|
4
4
|
expect(scan("%test \"a\" hi\n%%\nt: d { { } }\n%%\nhi\n")).to eq [
|
5
|
-
[:directive,
|
5
|
+
[:directive, 'test', %w(a hi)],
|
6
6
|
[:second],
|
7
|
-
[:label,
|
8
|
-
[:part,
|
9
|
-
[:block,
|
7
|
+
[:label, 't', nil],
|
8
|
+
[:part, 'd', nil],
|
9
|
+
[:block, '{ { } }'],
|
10
10
|
[:third],
|
11
11
|
[:copy, "\nhi\n"]
|
12
12
|
]
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'throws an error' do
|
16
16
|
expect {
|
17
|
-
scan(
|
17
|
+
scan('% %% %% ')
|
18
18
|
}.to raise_error(Ace::SyntaxError)
|
19
19
|
end
|
20
20
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
describe Generation::Constructor do
|
2
|
+
let(:grammar) { double('grammar') }
|
3
|
+
let(:terminal) { token(:TERMINAL) }
|
4
|
+
let(:epsilon) { token(:epsilon) }
|
5
|
+
|
6
|
+
subject { described_class.new(grammar) }
|
7
|
+
|
8
|
+
context '#nullable?' do
|
9
|
+
context 'when given an epsilon token' do
|
10
|
+
it 'returns true' do
|
11
|
+
expect(subject.nullable?(epsilon)).to be true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when given a terminal' do
|
16
|
+
it 'returns false' do
|
17
|
+
expect(subject.nullable?(terminal)).to be false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when given an array' do
|
22
|
+
context 'with one of the elements not nullable' do
|
23
|
+
it 'returns false' do
|
24
|
+
expect(subject.nullable?([terminal, epsilon])).to be false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with all of the elements nullable' do
|
29
|
+
it 'returns true' do
|
30
|
+
expect(subject.nullable?([epsilon, epsilon])).to be true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when given a nonterminal' do
|
36
|
+
let(:grammar) { with_recognizer }
|
37
|
+
|
38
|
+
context 'with no nullable productions' do
|
39
|
+
let(:nonterminal) { Grammar::Token::Nonterminal.new(:l) }
|
40
|
+
|
41
|
+
it 'returns false' do
|
42
|
+
expect(subject.nullable?(nonterminal)).to be false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'with a nullable production' do
|
47
|
+
let(:nonterminal) { Grammar::Token::Nonterminal.new(:e) }
|
48
|
+
|
49
|
+
it 'returns true' do
|
50
|
+
expect(subject.nullable?(nonterminal)).to be true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when given a bad argument' do
|
56
|
+
it 'raises an error' do
|
57
|
+
expect { subject.nullable?(nil) }.to raise_error(ArgumentError)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context '#first' do
|
63
|
+
context 'when given an epsilon token' do
|
64
|
+
it 'generates an empty set' do
|
65
|
+
expect(subject.first(epsilon)).to eq Set.new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when given a terminal' do
|
70
|
+
it 'generates a set' do
|
71
|
+
expect(subject.first(terminal)).to eq [terminal].to_set
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when given an array' do
|
76
|
+
let(:terminal2) { token(:terminal, :TERMINAL2) }
|
77
|
+
|
78
|
+
it 'generates a set' do
|
79
|
+
expect(subject.first([epsilon, terminal]))
|
80
|
+
.to eq [terminal].to_set
|
81
|
+
expect(subject.first([terminal, terminal2]))
|
82
|
+
.to eq [terminal].to_set
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when given a nonterminal' do
|
87
|
+
let(:grammar) { with_recognizer }
|
88
|
+
let(:nonterminal) { token(:nonterminal, :e) }
|
89
|
+
|
90
|
+
it 'generates a set' do
|
91
|
+
expect(subject.first(nonterminal))
|
92
|
+
.to eq [token(:terminal, :IDENT), token(:terminal, :STAR, '*')].to_set
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when given a bad argument' do
|
97
|
+
it 'raises an error' do
|
98
|
+
expect { subject.first(nil) }.to raise_error(ArgumentError)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context '#follow' do
|
104
|
+
context 'when given a bad argument' do
|
105
|
+
it 'raises an error' do
|
106
|
+
expect { subject.follow(nil) }.to raise_error(ArgumentError)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'when given a nonterminal' do
|
111
|
+
let(:grammar) { with_recognizer }
|
112
|
+
let(:nonterminal) { token(:nonterminal, :l) }
|
113
|
+
|
114
|
+
before do
|
115
|
+
subject.productions.merge grammar.productions.values.flatten
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'generates a set' do
|
119
|
+
expect(subject.follow(nonterminal)).to eq [
|
120
|
+
token(:terminal, :EQUALS, '='),
|
121
|
+
token(:terminal, :'$end')
|
122
|
+
].to_set
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def token(type, name = nil, value = nil, ttype = nil, id = nil)
|
128
|
+
type = Grammar::Token.const_get(type.to_s.capitalize)
|
129
|
+
type.new(name, ttype, id, value)
|
130
|
+
end
|
131
|
+
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module GrammarHelper
|
2
|
-
|
3
2
|
def grammar_for(grammar_file = "simple")
|
4
3
|
source_path = Pathname.new("../../fixtures").expand_path(__FILE__)
|
5
|
-
|
4
|
+
Grammar.from_file(source_path.children.select(&:file?)
|
6
5
|
.find { |x| x.to_s =~ /#{Regexp.escape(grammar_file)}\..*\z/ }.to_s)
|
7
6
|
end
|
8
7
|
|
9
8
|
def with_recognizer(grammar = simple_grammar)
|
10
|
-
|
9
|
+
Generation::Recognizer.new(grammar).call
|
11
10
|
grammar
|
12
11
|
end
|
13
12
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: antelope
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Rodi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -104,6 +104,7 @@ extra_rdoc_files: []
|
|
104
104
|
files:
|
105
105
|
- ".gitignore"
|
106
106
|
- ".rspec"
|
107
|
+
- ".rubocop.yml"
|
107
108
|
- ".travis.yml"
|
108
109
|
- ".yardopts"
|
109
110
|
- CONTRIBUTING.md
|
@@ -117,33 +118,32 @@ files:
|
|
117
118
|
- bin/antelope
|
118
119
|
- examples/deterministic.ace
|
119
120
|
- examples/example.ace
|
120
|
-
- examples/example.err
|
121
|
-
- examples/example.inf
|
121
|
+
- examples/example.ace.err
|
122
|
+
- examples/example.ace.inf
|
123
|
+
- examples/example.ate
|
124
|
+
- examples/example.ate.err
|
125
|
+
- examples/example.ate.inf
|
122
126
|
- examples/liquidscript.ace
|
123
127
|
- examples/simple.ace
|
124
128
|
- lib/antelope.rb
|
125
129
|
- lib/antelope/ace.rb
|
126
130
|
- lib/antelope/ace/compiler.rb
|
127
131
|
- lib/antelope/ace/errors.rb
|
128
|
-
- lib/antelope/ace/grammar.rb
|
129
|
-
- lib/antelope/ace/grammar/generation.rb
|
130
|
-
- lib/antelope/ace/grammar/loading.rb
|
131
|
-
- lib/antelope/ace/grammar/precedences.rb
|
132
|
-
- lib/antelope/ace/grammar/productions.rb
|
133
|
-
- lib/antelope/ace/grammar/symbols.rb
|
134
|
-
- lib/antelope/ace/precedence.rb
|
135
|
-
- lib/antelope/ace/production.rb
|
136
132
|
- lib/antelope/ace/scanner.rb
|
137
133
|
- lib/antelope/ace/scanner/argument.rb
|
138
134
|
- lib/antelope/ace/scanner/first.rb
|
139
135
|
- lib/antelope/ace/scanner/second.rb
|
140
136
|
- lib/antelope/ace/scanner/third.rb
|
141
|
-
- lib/antelope/ace/token.rb
|
142
|
-
- lib/antelope/ace/token/epsilon.rb
|
143
|
-
- lib/antelope/ace/token/error.rb
|
144
|
-
- lib/antelope/ace/token/nonterminal.rb
|
145
|
-
- lib/antelope/ace/token/terminal.rb
|
146
137
|
- lib/antelope/cli.rb
|
138
|
+
- lib/antelope/dsl.rb
|
139
|
+
- lib/antelope/dsl/compiler.rb
|
140
|
+
- lib/antelope/dsl/contexts.rb
|
141
|
+
- lib/antelope/dsl/contexts/base.rb
|
142
|
+
- lib/antelope/dsl/contexts/main.rb
|
143
|
+
- lib/antelope/dsl/contexts/match.rb
|
144
|
+
- lib/antelope/dsl/contexts/precedence.rb
|
145
|
+
- lib/antelope/dsl/contexts/production.rb
|
146
|
+
- lib/antelope/dsl/contexts/terminal.rb
|
147
147
|
- lib/antelope/errors.rb
|
148
148
|
- lib/antelope/generation.rb
|
149
149
|
- lib/antelope/generation/constructor.rb
|
@@ -179,6 +179,19 @@ files:
|
|
179
179
|
- lib/antelope/generator/templates/html/js.ant
|
180
180
|
- lib/antelope/generator/templates/info.ant
|
181
181
|
- lib/antelope/generator/templates/ruby.ant
|
182
|
+
- lib/antelope/grammar.rb
|
183
|
+
- lib/antelope/grammar/generation.rb
|
184
|
+
- lib/antelope/grammar/loading.rb
|
185
|
+
- lib/antelope/grammar/precedence.rb
|
186
|
+
- lib/antelope/grammar/precedences.rb
|
187
|
+
- lib/antelope/grammar/production.rb
|
188
|
+
- lib/antelope/grammar/productions.rb
|
189
|
+
- lib/antelope/grammar/symbols.rb
|
190
|
+
- lib/antelope/grammar/token.rb
|
191
|
+
- lib/antelope/grammar/token/epsilon.rb
|
192
|
+
- lib/antelope/grammar/token/error.rb
|
193
|
+
- lib/antelope/grammar/token/nonterminal.rb
|
194
|
+
- lib/antelope/grammar/token/terminal.rb
|
182
195
|
- lib/antelope/template.rb
|
183
196
|
- lib/antelope/template/compiler.rb
|
184
197
|
- lib/antelope/template/errors.rb
|
@@ -187,7 +200,7 @@ files:
|
|
187
200
|
- optimizations.txt
|
188
201
|
- spec/antelope/ace/compiler_spec.rb
|
189
202
|
- spec/antelope/ace/scanner_spec.rb
|
190
|
-
- spec/antelope/constructor_spec.rb
|
203
|
+
- spec/antelope/generation/constructor_spec.rb
|
191
204
|
- spec/antelope/template_spec.rb
|
192
205
|
- spec/fixtures/simple.ace
|
193
206
|
- spec/spec_helper.rb
|
@@ -222,7 +235,7 @@ summary: A compiler compiler, written in ruby.
|
|
222
235
|
test_files:
|
223
236
|
- spec/antelope/ace/compiler_spec.rb
|
224
237
|
- spec/antelope/ace/scanner_spec.rb
|
225
|
-
- spec/antelope/constructor_spec.rb
|
238
|
+
- spec/antelope/generation/constructor_spec.rb
|
226
239
|
- spec/antelope/template_spec.rb
|
227
240
|
- spec/fixtures/simple.ace
|
228
241
|
- spec/spec_helper.rb
|
@@ -1,80 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Antelope
|
4
|
-
module Ace
|
5
|
-
class Grammar
|
6
|
-
|
7
|
-
# The default modifiers for generation. It's not really
|
8
|
-
# recommended to (heh) modify this; however, adding your own
|
9
|
-
# modifier is always acceptable.
|
10
|
-
DEFAULT_MODIFIERS = [
|
11
|
-
[:recognizer, Generation::Recognizer ],
|
12
|
-
[:constructor, Generation::Constructor],
|
13
|
-
[:tableizer, Generation::Tableizer ]
|
14
|
-
].freeze
|
15
|
-
|
16
|
-
# Handles the generation of output for the grammar.
|
17
|
-
module Generation
|
18
|
-
|
19
|
-
# Generates the output. First, it runs through every given
|
20
|
-
# modifier, and instintates it. It then calls every modifier,
|
21
|
-
# turns it into a hash, and passes that hash to each of the
|
22
|
-
# given generators.
|
23
|
-
#
|
24
|
-
# @param options [Hash] options.
|
25
|
-
# @param generators [Array<Generator>] a list of generators
|
26
|
-
# to use in generation.
|
27
|
-
# @param modifiers [Array<Array<(Symbol, #call)>>] a list of
|
28
|
-
# modifiers to apply to the grammar.
|
29
|
-
# @return [void]
|
30
|
-
def generate(options = {},
|
31
|
-
generators = :guess,
|
32
|
-
modifiers = DEFAULT_MODIFIERS)
|
33
|
-
mods = modifiers.map(&:last).
|
34
|
-
map { |x| x.new(self) }
|
35
|
-
mods.each do |mod|
|
36
|
-
puts "Running mod #{mod.class}..." if options[:verbose]
|
37
|
-
mod.call
|
38
|
-
end
|
39
|
-
hash = Hash[modifiers.map(&:first).zip(mods)]
|
40
|
-
# This is when we'd generate
|
41
|
-
|
42
|
-
find_generators(generators, options).each do |gen|
|
43
|
-
puts "Running generator #{gen}..." if options[:verbose]
|
44
|
-
gen.new(self, hash).generate
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
# Find the corresponding generators. If the first argument
|
51
|
-
# isn't `:guess`, it returns the first argument. Otherwise,
|
52
|
-
# it tries to "intelligently guess" by checking the type from
|
53
|
-
# the options _or_ the compiler. If it is unable to find the
|
54
|
-
# type, it will raise a {NoTypeError}.
|
55
|
-
#
|
56
|
-
# @raise [NoTypeError] if it could not determine the type of
|
57
|
-
# the generator.
|
58
|
-
# @param generators [Symbol, Array<Generator>]
|
59
|
-
# @param options [Hash]
|
60
|
-
# @return [Array<Generator>]
|
61
|
-
def find_generators(generators, options)
|
62
|
-
return generators unless generators == :guess
|
63
|
-
|
64
|
-
generators = [Generator::Output]
|
65
|
-
|
66
|
-
# command line precedence...
|
67
|
-
type = options[:type] || options["type"] ||
|
68
|
-
compiler.options.fetch(:type)
|
69
|
-
|
70
|
-
generators << Generator.generators.fetch(type)
|
71
|
-
|
72
|
-
generators
|
73
|
-
|
74
|
-
rescue KeyError
|
75
|
-
raise NoTypeError, "Undefined type #{type}"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Antelope
|
4
|
-
module Ace
|
5
|
-
class Grammar
|
6
|
-
|
7
|
-
# Handles loading to and from files and strings.
|
8
|
-
module Loading
|
9
|
-
|
10
|
-
# Defines class methods on the grammar.
|
11
|
-
module ClassMethods
|
12
|
-
|
13
|
-
# Loads a grammar from a file. Assumes the output
|
14
|
-
# directory and name from the file name.
|
15
|
-
#
|
16
|
-
# @param file_name [String] the file name.
|
17
|
-
# @return [Grammar]
|
18
|
-
# @see #from_string
|
19
|
-
def from_file(file_name)
|
20
|
-
body = File.read(file_name)
|
21
|
-
output = File.dirname(file_name)
|
22
|
-
name = File.basename(file_name).gsub(/\.[A-Za-z]+/, "")
|
23
|
-
from_string(name, output, body)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Loads a grammar from a string. First runs the scanner and
|
27
|
-
# compiler over the string, and then instantiates a new
|
28
|
-
# Grammar from the resultant.
|
29
|
-
#
|
30
|
-
# @param name [String] the name of the grammar.
|
31
|
-
# @param output [String] the output directory.
|
32
|
-
# @param string [String] the grammar body.
|
33
|
-
# @return [Grammar]
|
34
|
-
# @see Ace::Scanner
|
35
|
-
# @see Ace::Compiler
|
36
|
-
def from_string(name, output, string)
|
37
|
-
scanner = Ace::Scanner.scan(string, name)
|
38
|
-
compiler = Ace::Compiler.compile(scanner)
|
39
|
-
new(name, output, compiler)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Extends the grammar with the class methods.
|
44
|
-
#
|
45
|
-
# @param receiver [Grammar]
|
46
|
-
# @see ClassMethods
|
47
|
-
def self.included(receiver)
|
48
|
-
receiver.extend ClassMethods
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "set"
|
4
|
-
|
5
|
-
module Antelope
|
6
|
-
module Ace
|
7
|
-
class Grammar
|
8
|
-
|
9
|
-
# Manages precedence for tokens.
|
10
|
-
module Precedences
|
11
|
-
|
12
|
-
# Accesses the generated precedence list. Lazily generates
|
13
|
-
# the precedence rules on the go, and then caches it.
|
14
|
-
#
|
15
|
-
# @return [Array<Ace::Precedence>]
|
16
|
-
def precedence
|
17
|
-
@_precedence ||= generate_precedence
|
18
|
-
end
|
19
|
-
|
20
|
-
# Finds a precedence rule for a given token. If no direct
|
21
|
-
# rule is defined for that token, it will check for a rule
|
22
|
-
# defined for the special symbol, `:_`. By default, there
|
23
|
-
# is always a rule defined for `:_`.
|
24
|
-
#
|
25
|
-
# @param token [Ace::Token, Symbol]
|
26
|
-
# @return [Ace::Precedence]
|
27
|
-
def precedence_for(token)
|
28
|
-
token = token.name if token.is_a?(Token)
|
29
|
-
|
30
|
-
prec = precedence.
|
31
|
-
detect { |pr| pr.tokens.include?(token) } ||
|
32
|
-
precedence.
|
33
|
-
detect { |pr| pr.tokens.include?(:_) }
|
34
|
-
|
35
|
-
prec
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
# Generates the precedence rules. Loops through the compiler
|
41
|
-
# given precedence settings, and then adds two default
|
42
|
-
# precedence rules; one for `:$` (level 0, nonassoc), and one
|
43
|
-
# for `:_` (level 1, nonassoc).
|
44
|
-
#
|
45
|
-
# @return [Array<Ace::Precedence>]
|
46
|
-
def generate_precedence
|
47
|
-
size = @compiler.options[:prec].size + 1
|
48
|
-
index = 0
|
49
|
-
precedence = []
|
50
|
-
|
51
|
-
while index < size - 1
|
52
|
-
prec = @compiler.options[:prec][index]
|
53
|
-
precedence <<
|
54
|
-
Ace::Precedence.new(prec[0], prec[1..-1].to_set,
|
55
|
-
size - index)
|
56
|
-
index += 1
|
57
|
-
end
|
58
|
-
|
59
|
-
precedence <<
|
60
|
-
Ace::Precedence.new(:nonassoc, [:$end].to_set, 0) <<
|
61
|
-
Ace::Precedence.new(:nonassoc, [:_].to_set, 1)
|
62
|
-
precedence.sort_by(&:level).reverse
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|