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