antlr3 1.3.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3/task.rb +443 -0
- data/lib/antlr3/test/grammar.rb +0 -2
- data/lib/antlr3/tree.rb +1 -0
- data/lib/antlr3/version.rb +1 -1
- data/templates/Ruby.stg +2 -2
- metadata +2 -2
data/java/antlr-full-3.2.1.jar
CHANGED
Binary file
|
data/lib/antlr3/task.rb
CHANGED
@@ -1,13 +1,456 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
|
+
require 'antlr3'
|
4
5
|
require 'rake/tasklib'
|
6
|
+
require 'shellwords'
|
5
7
|
|
6
8
|
module ANTLR3
|
9
|
+
|
10
|
+
=begin rdoc ANTLR3::CompileTask
|
11
|
+
|
12
|
+
A rake task-generating utility concerning ANTLR grammar file
|
13
|
+
compilation. This is a general utility -- the grammars do
|
14
|
+
not have to be targetted for Ruby output; it handles all
|
15
|
+
known ANTLR language targets.
|
16
|
+
|
17
|
+
require 'antlr3/task'
|
18
|
+
|
19
|
+
ANTLR3::CompileTask.define(
|
20
|
+
:name => 'grammars', :output_directory => 'lib/parsers'
|
21
|
+
) do | t |
|
22
|
+
t.grammar_set( 'antlr/MainParser.g', 'antlr/MainTree.g' )
|
23
|
+
|
24
|
+
t.grammar_set( 'antlr/Template.g' ) do | gram |
|
25
|
+
gram.output_directory = 'lib/parsers/template'
|
26
|
+
gram.debug = true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
TODO: finish documentation
|
32
|
+
|
33
|
+
=end
|
34
|
+
|
7
35
|
class CompileTask < Rake::TaskLib
|
36
|
+
attr_reader :grammar_sets, :options
|
37
|
+
attr_accessor :name
|
38
|
+
|
39
|
+
def self.define( *grammar_files )
|
40
|
+
lib = new( *grammar_files )
|
41
|
+
block_given? and yield( lib )
|
42
|
+
lib.define
|
43
|
+
return( lib )
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize( *grammar_files )
|
47
|
+
grammar_files = [ grammar_files ].flatten!
|
48
|
+
options = Hash === grammar_files.last ? grammar_files.pop : {}
|
49
|
+
@grammar_sets = []
|
50
|
+
@name = options.fetch( :name, 'antlr-grammars' )
|
51
|
+
@options = options
|
52
|
+
grammar_files.empty? or grammar_set( grammar_files )
|
53
|
+
end
|
54
|
+
|
55
|
+
def target_files
|
56
|
+
@grammar_sets.inject( [] ) do | list, set |
|
57
|
+
list.concat( set.target_files )
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def grammar_set( *grammar_files )
|
62
|
+
grammar_files = [ grammar_files ].flatten!
|
63
|
+
options = @options.merge(
|
64
|
+
Hash === grammar_files.last ? grammar_files.pop : {}
|
65
|
+
)
|
66
|
+
set = GrammarSet.new( grammar_files, options )
|
67
|
+
block_given? and yield( set )
|
68
|
+
@grammar_sets << set
|
69
|
+
return( set )
|
70
|
+
end
|
8
71
|
|
72
|
+
def define
|
73
|
+
namespace( @name ) do
|
74
|
+
desc( "trash all ANTLR-generated source code")
|
75
|
+
task( 'clobber' ) do
|
76
|
+
for set in @grammar_sets
|
77
|
+
set.clean
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
for set in @grammar_sets
|
82
|
+
set.define_tasks
|
83
|
+
end
|
84
|
+
|
85
|
+
desc( "compile ANTLR grammars" )
|
86
|
+
task( 'compile' => target_files )
|
87
|
+
end
|
88
|
+
end
|
9
89
|
|
90
|
+
|
91
|
+
class CompileTask::GrammarSet
|
92
|
+
attr_accessor :antlr_jar, :debug,
|
93
|
+
:trace, :profile, :compile_options,
|
94
|
+
:java_options
|
95
|
+
attr_reader :load_path, :grammars
|
96
|
+
attr_writer :output_directory
|
97
|
+
|
98
|
+
def initialize( grammar_files, options = {} )
|
99
|
+
@load_path = grammar_files.map { | f | File.dirname( f ) }
|
100
|
+
@load_path.push( '.', @output_directory )
|
101
|
+
|
102
|
+
if extra_load = options[ :load_path ]
|
103
|
+
extra_load = [ extra_load ].flatten
|
104
|
+
@load_path.unshift( extra_load )
|
105
|
+
end
|
106
|
+
@load_path.uniq!
|
107
|
+
|
108
|
+
@grammars = grammar_files.map do | file |
|
109
|
+
GrammarFile.new( self, file )
|
110
|
+
end
|
111
|
+
@output_directory = nil
|
112
|
+
dir = options[ :output_directory ] and @output_directory = dir.to_s
|
113
|
+
|
114
|
+
@antlr_jar = options.fetch( :antlr_jar, ANTLR3.antlr_jar )
|
115
|
+
@debug = options.fetch( :debug, false )
|
116
|
+
@trace = options.fetch( :trace, false )
|
117
|
+
@profile = options.fetch( :profile, false )
|
118
|
+
@compile_options =
|
119
|
+
case opts = options[ :compile_options ]
|
120
|
+
when Array then opts
|
121
|
+
else Shellwords.shellsplit( opts.to_s )
|
122
|
+
end
|
123
|
+
@java_options =
|
124
|
+
case opts = options[ :java_options ]
|
125
|
+
when Array then opts
|
126
|
+
else Shellwords.shellsplit( opts.to_s )
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def target_files
|
131
|
+
@grammars.map { | gram | gram.target_files }.flatten
|
132
|
+
end
|
133
|
+
|
134
|
+
def output_directory
|
135
|
+
@output_directory || '.'
|
136
|
+
end
|
137
|
+
|
138
|
+
def define_tasks
|
139
|
+
directory( @output_directory )
|
140
|
+
file( @antlr_jar )
|
141
|
+
|
142
|
+
for grammar in @grammars
|
143
|
+
deps = [ @output_directory, @antlr_jar ]
|
144
|
+
if vocab = grammar.token_vocab and
|
145
|
+
tfile = find_tokens_file( vocab, grammar )
|
146
|
+
file( tfile )
|
147
|
+
deps << tfile
|
148
|
+
end
|
149
|
+
grammar.define_tasks( deps )
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def clean
|
154
|
+
for grammar in @grammars
|
155
|
+
grammar.clean
|
156
|
+
end
|
157
|
+
if test( ?d, output_directory ) and ( Dir.entries( output_directory ) - %w( . .. ) ).empty?
|
158
|
+
rmdir( output_directory )
|
159
|
+
end
|
160
|
+
end
|
10
161
|
|
162
|
+
def find_tokens_file( vocab, grammar )
|
163
|
+
gram = @grammars.find { | gram | gram.name == vocab } and
|
164
|
+
return( gram.tokens_file )
|
165
|
+
file = locate( "#{ vocab }.tokens" ) and return( file )
|
166
|
+
warn( Util.tidy( <<-END, true ) )
|
167
|
+
| unable to locate .tokens file `#{ vocab }' referenced in #{ grammar.path }
|
168
|
+
| -- ignoring dependency
|
169
|
+
END
|
170
|
+
return( nil )
|
171
|
+
end
|
11
172
|
|
173
|
+
def locate( file_name )
|
174
|
+
dir = @load_path.find do | dir |
|
175
|
+
File.file?( File.join( dir, file_name ) )
|
176
|
+
end
|
177
|
+
dir and return( File.join( dir, file_name ) )
|
178
|
+
end
|
179
|
+
|
180
|
+
def compile( grammar )
|
181
|
+
sh( build_command( grammar ) )
|
182
|
+
end
|
183
|
+
|
184
|
+
def build_command( grammar )
|
185
|
+
parts = [ 'java', '-cp', @antlr_jar ]
|
186
|
+
parts.concat( @java_options )
|
187
|
+
parts << 'org.antlr.Tool' << '-fo' << output_directory
|
188
|
+
parts << '-debug' if @debug
|
189
|
+
parts << '-profile' if @profile
|
190
|
+
parts << '-trace' if @trace
|
191
|
+
parts.concat( @compile_options )
|
192
|
+
parts << grammar.path
|
193
|
+
return Shellwords.shelljoin( parts )
|
194
|
+
end
|
12
195
|
end
|
196
|
+
|
197
|
+
class GrammarFile
|
198
|
+
LANGUAGES = {
|
199
|
+
"ActionScript" => [".as"],
|
200
|
+
"CSharp2" => [".cs"],
|
201
|
+
"C" => [".c", ".h"],
|
202
|
+
"ObjC" => [".m", ".h"],
|
203
|
+
"CSharp3" => [".cs"],
|
204
|
+
"Cpp" => [".cpp", ".h"],
|
205
|
+
"Ruby" => [".rb"],
|
206
|
+
"Java" => [".java"],
|
207
|
+
"JavaScript" => [".js"],
|
208
|
+
"Python" => [".py"],
|
209
|
+
"Delphi" => [".pas"],
|
210
|
+
"Perl5" => [".pm"]
|
211
|
+
}.freeze
|
212
|
+
GRAMMAR_TYPES = %w(lexer parser tree combined)
|
213
|
+
|
214
|
+
##################################################################
|
215
|
+
######## CONSTRUCTOR #############################################
|
216
|
+
##################################################################
|
217
|
+
|
218
|
+
def initialize( group, path, options = {} )
|
219
|
+
@group = group
|
220
|
+
@path = path.to_s
|
221
|
+
@imports = []
|
222
|
+
@language = 'Java'
|
223
|
+
@token_vocab = nil
|
224
|
+
@tasks_defined = false
|
225
|
+
@extra_dependencies = []
|
226
|
+
if extra = options[ :extra_dependencies ]
|
227
|
+
extra = [ extra ].flatten
|
228
|
+
@extra_dependencies.concat( extra )
|
229
|
+
end
|
230
|
+
|
231
|
+
study
|
232
|
+
yield( self ) if block_given?
|
233
|
+
fetch_imports
|
234
|
+
end
|
235
|
+
|
236
|
+
##################################################################
|
237
|
+
######## ATTRIBUTES AND ATTRIBUTE-ISH METHODS ####################
|
238
|
+
##################################################################
|
239
|
+
attr_reader :type, :name, :language, :source,
|
240
|
+
:token_vocab, :imports, :imported_grammars,
|
241
|
+
:path, :group
|
242
|
+
|
243
|
+
for attr in [ :output_directory, :load_path, :antlr_jar ]
|
244
|
+
class_eval( <<-END )
|
245
|
+
def #{ attr }
|
246
|
+
@group.#{ attr }
|
247
|
+
end
|
248
|
+
END
|
249
|
+
end
|
250
|
+
|
251
|
+
def lexer_files
|
252
|
+
if lexer? then base = @name
|
253
|
+
elsif combined? then base = @name + 'Lexer'
|
254
|
+
else return( [] )
|
255
|
+
end
|
256
|
+
return( file_names( base ) )
|
257
|
+
end
|
258
|
+
|
259
|
+
def parser_files
|
260
|
+
if parser? then base = @name
|
261
|
+
elsif combined? then base = @name + 'Parser'
|
262
|
+
else return( [] )
|
263
|
+
end
|
264
|
+
return( file_names( base ) )
|
265
|
+
end
|
266
|
+
|
267
|
+
def tree_parser_files
|
268
|
+
return( tree? ? file_names( @name ) : [] )
|
269
|
+
end
|
270
|
+
|
271
|
+
def file_names( base )
|
272
|
+
LANGUAGES.fetch( @language ).map do | ext |
|
273
|
+
File.join( output_directory, base + ext )
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
for type in GRAMMAR_TYPES
|
278
|
+
class_eval( <<-END )
|
279
|
+
def #{ type }?
|
280
|
+
@type == #{ type.inspect }
|
281
|
+
end
|
282
|
+
END
|
283
|
+
end
|
284
|
+
|
285
|
+
def delegate_files( delegate_suffix )
|
286
|
+
file_names( "#{ name }_#{ delegate_suffix }" )
|
287
|
+
end
|
288
|
+
|
289
|
+
def tokens_file
|
290
|
+
File.join( output_directory, name + '.tokens' )
|
291
|
+
end
|
292
|
+
|
293
|
+
def target_files( all = true )
|
294
|
+
targets = [ tokens_file ]
|
295
|
+
|
296
|
+
for target_type in %w( lexer parser tree_parser )
|
297
|
+
for file in self.send( :"#{ target_type }_files")
|
298
|
+
targets << file
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
if all
|
303
|
+
for grammar in @imported_grammars
|
304
|
+
targets.concat( grammar.target_files )
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
return targets
|
309
|
+
end
|
310
|
+
|
311
|
+
def update
|
312
|
+
touch( @path )
|
313
|
+
end
|
314
|
+
|
315
|
+
def all_imported_files
|
316
|
+
imported_files = []
|
317
|
+
for grammar in @imported_grammars
|
318
|
+
imported_files.push( grammar.path, *grammar.all_imported_files )
|
319
|
+
end
|
320
|
+
return imported_files
|
321
|
+
end
|
322
|
+
|
323
|
+
def clean
|
324
|
+
deleted = []
|
325
|
+
for target in target_files
|
326
|
+
if test( ?f, target )
|
327
|
+
rm( target )
|
328
|
+
deleted << target
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
for grammar in @imported_grammars
|
333
|
+
deleted.concat( grammar.clean )
|
334
|
+
end
|
335
|
+
|
336
|
+
return deleted
|
337
|
+
end
|
338
|
+
|
339
|
+
def define_tasks( shared_depends )
|
340
|
+
unless @tasks_defined
|
341
|
+
depends = [ @path, *all_imported_files ]
|
342
|
+
for f in depends
|
343
|
+
file( f )
|
344
|
+
end
|
345
|
+
depends = shared_depends + depends
|
346
|
+
|
347
|
+
target_files.each do | target |
|
348
|
+
file( target => depends ) do
|
349
|
+
@group.compile( self )
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
@tasks_defined = true
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
private
|
358
|
+
|
359
|
+
def fetch_imports
|
360
|
+
@imported_grammars = @imports.map do | imp |
|
361
|
+
file = group.locate( "#{ imp }.g" ) or raise( Util.tidy( <<-END ) )
|
362
|
+
| #{ @path }: unable to locate imported grammar file #{ imp }.g
|
363
|
+
| search directories ( @load_path ):
|
364
|
+
| - #{ load_path.join( "\n - " ) }
|
365
|
+
END
|
366
|
+
Imported.new( self, file )
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
def study
|
371
|
+
@source = File.read( @path )
|
372
|
+
@source =~ /^\s*(lexer|parser|tree)?\s*grammar\s*(\S+)\s*;/ or
|
373
|
+
raise Grammar::FormatError[ @source, @path ]
|
374
|
+
@name = $2
|
375
|
+
@type = $1 || 'combined'
|
376
|
+
if @source =~ /^\s*options\s*\{(.*?)\}/m
|
377
|
+
option_block = $1
|
378
|
+
if option_block =~ /\s*language\s*=\s*(\S+)\s*;/
|
379
|
+
@language = $1
|
380
|
+
LANGUAGES.has_key?( @language ) or
|
381
|
+
raise( Grammar::FormatError, "Unknown ANTLR target language: %p" % @language )
|
382
|
+
end
|
383
|
+
option_block =~ /\s*tokenVocab\s*=\s*(\S+)\s*;/ and
|
384
|
+
@token_vocab = $1
|
385
|
+
end
|
386
|
+
|
387
|
+
@source.scan(/^\s*import\s+(\w+\s*(?:,\s*\w+\s*)*);/) do
|
388
|
+
list = $1.strip
|
389
|
+
@imports.concat( list.split( /\s*,\s*/ ) )
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end # class Grammar
|
393
|
+
|
394
|
+
class GrammarFile::Imported < GrammarFile
|
395
|
+
def initialize( owner, path )
|
396
|
+
@owner = owner
|
397
|
+
@path = path.to_s
|
398
|
+
@imports = []
|
399
|
+
@language = 'Java'
|
400
|
+
@token_vocab = nil
|
401
|
+
study
|
402
|
+
fetch_imports
|
403
|
+
end
|
404
|
+
|
405
|
+
for attr in [ :load_path, :output_directory, :antlr_jar, :verbose, :group ]
|
406
|
+
class_eval( <<-END )
|
407
|
+
def #{ attr }
|
408
|
+
@owner.#{ attr }
|
409
|
+
end
|
410
|
+
END
|
411
|
+
end
|
412
|
+
|
413
|
+
def delegate_files( suffix )
|
414
|
+
@owner.delegate_files( "#{ @name }_#{ suffix }" )
|
415
|
+
end
|
416
|
+
|
417
|
+
def target_files
|
418
|
+
targets = [ tokens_file ]
|
419
|
+
targets.concat( @owner.delegate_files( @name ) )
|
420
|
+
return( targets )
|
421
|
+
end
|
13
422
|
end
|
423
|
+
|
424
|
+
class GrammarFile::FormatError < StandardError
|
425
|
+
attr_reader :file, :source
|
426
|
+
|
427
|
+
def self.[](*args)
|
428
|
+
new(*args)
|
429
|
+
end
|
430
|
+
|
431
|
+
def initialize(source, file = nil)
|
432
|
+
@file = file
|
433
|
+
@source = source
|
434
|
+
message = ''
|
435
|
+
if file.nil? # inline
|
436
|
+
message << "bad inline grammar source:\n"
|
437
|
+
message << ("-" * 80) << "\n"
|
438
|
+
message << @source
|
439
|
+
message[-1] == ?\n or message << "\n"
|
440
|
+
message << ("-" * 80) << "\n"
|
441
|
+
message << "could not locate a grammar name and type declaration matching\n"
|
442
|
+
message << "/^\s*(lexer|parser|tree)?\s*grammar\s*(\S+)\s*;/"
|
443
|
+
else
|
444
|
+
message << 'bad grammar source in file %p' % @file
|
445
|
+
message << ("-" * 80) << "\n"
|
446
|
+
message << @source
|
447
|
+
message[-1] == ?\n or message << "\n"
|
448
|
+
message << ("-" * 80) << "\n"
|
449
|
+
message << "could not locate a grammar name and type declaration matching\n"
|
450
|
+
message << "/^\s*(lexer|parser|tree)?\s*grammar\s*(\S+)\s*;/"
|
451
|
+
end
|
452
|
+
super(message)
|
453
|
+
end
|
454
|
+
end # error Grammar::FormatError
|
455
|
+
end # class CompileTask
|
456
|
+
end # module ANTLR3
|
data/lib/antlr3/test/grammar.rb
CHANGED
@@ -5,7 +5,6 @@ require 'antlr3'
|
|
5
5
|
require 'antlr3/test/core-extensions'
|
6
6
|
require 'antlr3/test/call-stack'
|
7
7
|
|
8
|
-
|
9
8
|
if RUBY_VERSION =~ /^1\.9/
|
10
9
|
require 'digest/md5'
|
11
10
|
MD5 = Digest::MD5
|
@@ -13,7 +12,6 @@ else
|
|
13
12
|
require 'md5'
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
15
|
module ANTLR3
|
18
16
|
module Test
|
19
17
|
module DependantFile
|
data/lib/antlr3/tree.rb
CHANGED
data/lib/antlr3/version.rb
CHANGED
data/templates/Ruby.stg
CHANGED
@@ -28,7 +28,7 @@ $:.unshift( this_directory ) unless $:.include?( this_directory )
|
|
28
28
|
|
29
29
|
antlr_load_failed = proc do
|
30
30
|
load_path = $LOAD_PATH.map { |dir| ' - ' \<\< dir }.join( $/ )
|
31
|
-
raise LoadError, \<\<-
|
31
|
+
raise LoadError, \<\<-END.strip!
|
32
32
|
|
33
33
|
Failed to load the ANTLR3 runtime library (version <runtimeLibraryVersion()>):
|
34
34
|
|
@@ -1498,4 +1498,4 @@ placeAction(scope, name) ::= <<
|
|
1498
1498
|
<endif>
|
1499
1499
|
>>
|
1500
1500
|
|
1501
|
-
runtimeLibraryVersion() ::= "1.3.
|
1501
|
+
runtimeLibraryVersion() ::= "1.3.1"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: antlr3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Yetter
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-07 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|