/usr/bin/tt is in treetop 1.4.14-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #!/usr/bin/env ruby
require 'optparse'
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
require 'treetop'
require 'treetop/version'
require 'treetop/polyglot'
options = {}
parser = OptionParser.new do |opts|
exts = Treetop::Polyglot::VALID_GRAMMAR_EXT.collect { |i| '.' + i }
opts.banner = "Treetop Parsing Expression Grammar (PEG) Comand Line Compiler"
opts.define_head "Usage: tt [options] grammar_file[#{exts.join('|')}] ..."
opts.separator ''
opts.separator 'Examples:'
opts.separator ' tt foo.tt # 1 grammar -> 1 parser source'
opts.separator ' tt foo bar.treetop # 2 grammars -> 2 separate parsers'
opts.separator ' tt -o alt_name.rb foo # alternately named output file'
opts.separator ''
opts.separator ''
opts.separator 'NOTE: while treetop grammar files *must* have one of the following'
opts.separator 'filename extensions, the extension name is not required when calling'
opts.separator 'the compiler with grammar file names.'
opts.separator ''
opts.separator " Valid extensions: #{exts.join(', ')}"
opts.separator ''
opts.separator ''
opts.separator 'Options:'
opts.on('-o', '--output FILENAME', 'Write parser source to FILENAME') do |fn|
options[:out_file] = fn
end
opts.on('-f', '--force', 'Overwrite existing output file(s)') do
options[:force] = true
end
opts.on_tail('-v', '--version', 'Show Treetop version') do
puts "Treetop v#{Treetop::VERSION::STRING}"
exit
end
opts.on_tail('-h', '--help', 'Show this help message') do
puts opts
exit
end
end
file_list = parser.parse!
# check options and arg constraints
if file_list.empty? || (options[:out_file] && file_list.size > 1)
puts parser
exit 1
end
def grammar_exist?(filename)
if File.extname(filename).empty?
Treetop::Polyglot::VALID_GRAMMAR_EXT.each do |ext|
fn_ext = "#{filename}.#{ext}"
return true if File.exist?(fn_ext) && !File.zero?(fn_ext)
end
end
File.exist?(filename) && !File.zero?(filename)
end
def full_grammar_filename(filename)
return filename if !File.extname(filename).empty?
Treetop::Polyglot::VALID_GRAMMAR_EXT.each do |ext|
fn_ext = "#{filename}.#{ext}"
return fn_ext if File.exist?(fn_ext) && !File.zero?(fn_ext)
end
end
def protect_output?(filename, forced=false)
if !forced and
File.exist?(filename) and
File.open(filename) { |f| ![(f.gets rescue ''), (f.gets rescue '')].include? Treetop::Compiler::AUTOGENERATED }
puts "ERROR: '#{filename}' output already exists; skipping compilation...\n"
return true
end
false
end
compiler = Treetop::Compiler::GrammarCompiler.new
while !file_list.empty?
treetop_file = file_list.shift
# handle nonexistent and existent grammar files mixed together
if !grammar_exist?(treetop_file)
puts "ERROR: input grammar file '#{treetop_file}' does not exist; continuing...\n"
next
end
# try to compile
treetop_file = full_grammar_filename(treetop_file)
std_output_file = treetop_file.gsub(Treetop::Polyglot::VALID_GRAMMAR_EXT_REGEXP, '.rb')
if options[:out_file]
# explicit output file name option; never overwrite unless forced
next if protect_output?(options[:out_file], options[:force])
compiler.compile(treetop_file, options[:out_file])
else
# compile one input file from input file list option; never overwrite unless forced
next if protect_output?(std_output_file, options[:force])
compiler.compile(treetop_file)
end
end
|