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 112 113 114 115 116 117 118 119
|
#!/usr/bin/env jruby
#
# == Synopsis
#
# ast: Display information in the AST
#
# == Usage
#
# ast [OPTION] ... script.rb
#
# -h, --help:
# Display this help
#
# -s, --sexp:
# Display the S-Expression for the AST
#
# --source:
# Display the source
#
# --no-ast
# Do not print out the AST for this (only useful with -s)
#
# -e:
# Expression to try: 'ast -e "puts 1"'
#
# script.rb: The script to execute
require 'getoptlong'
require 'rdoc/usage'
opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--sexp', '-s', GetoptLong::NO_ARGUMENT ],
[ '--no-ast', GetoptLong::NO_ARGUMENT ],
[ '--source', GetoptLong::NO_ARGUMENT ],
[ '--expression', '-e', GetoptLong::REQUIRED_ARGUMENT ]
)
print_source = false
print_sexp = false
print_ast = true
expression = nil
opts.each do |opt, arg|
case opt
when '--help'
RDoc::usage
when '--sexp'
print_sexp = true
when '--no-ast'
print_ast = false
when '--expression'
expression = arg
when '--source'
print_source = true
end
end
if ARGV.length > 1
puts "You may only specify one script (see --help)"
exit 0
elsif ARGV.length == 1
if expression
puts "-e and a script is not a valid combination (see --help)"
exit 0
end
expression = File.read(ARGV.shift)
elsif !expression
puts "No script specified (see --help)"
exit 0
end
require 'jruby'
$indent_string = " "
def indexes(string, lindex, rindex)
lindex = string.index("(", lindex) if lindex != nil
rindex = string.index(")", rindex) if rindex != nil
return lindex, rindex
end
def indent(string)
depth = -1
lindex, rindex = indexes(string, 0, 0)
while (lindex != nil || rindex != nil)
if (lindex != nil && lindex < rindex)
depth += 1
string[lindex, 1] = "\n#{$indent_string * depth}"
else
depth -= 1
string[rindex, 1] = "\n"
end
lindex, rindex = indexes(string, lindex, rindex)
end
string.gsub(/,\s*$/, '').squeeze("\n")
end
root = JRuby.parse(expression)
if print_source
puts "Source:"
puts expression
puts
end
if print_ast
print "AST:"
puts indent(root.to_string)
puts
end
if print_sexp
puts "SEXP:"
puts org.jruby.ast.util.SexpMaker.create(root)
end
|