def gettoken
@token = '*** debug ***'
@token_str = '*** debug ***'
while (ch = getchar()) != nil do
if space?(ch) then
next
end
if ch == ?\# then
while (ch = getchar()) != ?\n && ch != nil do; end
next
end
break
end
if ch == nil then
@token = @token_str = nil
return @token
end
if alpha?(ch) then
s = ch.chr
s << getchar() while word?(nextchar())
@token_str = s
case s
when 'true'
@token = :true
when 'false'
@token = :false
when 'null', 'nil'
@token = :null
when 'empty'
@token = :empty
else
@token = :name
end
return @token
end
if num?(ch) then
s = ch.chr
s << getchar() while num?(nextchar())
if nextchar() == ?. then
s << getchar()
s << getchar() while num?(nextchar())
end
@token_str = s
@token = :number
return @token
end
if ch == ?\: then
s = ':'
if nextchar() == ?\: then
getchar()
if nextchar() == ?\: then
getchar()
@token = ':::'
@token_str = cutstr(?\n)
@token_str.chomp!
else
@token = '::'
@token_str = cutstr(?\n)
@token_str.chomp!
end
elsif alpha?(nextchar()) then
s << getchar() while alpha?(nextchar())
@token_str = s
@token = Keywords[s]
unless @token != nil
raise SyntaxError.new("'#{s}': invalid token.", self)
end
else
@token = @token_str = ':'
end
return @token
end
if ch == ?' then
s = ""
while (ch = getchar()) != ?' do
if ch == ?\\ then
case ch = getchar()
when ?n
ch = ?\n
end
end
s << ch
end
@token_str = s
@token = :string
return @token
end
case ch
when ?(, ?), ?{, ?}, ?]
@token = @token_str = ch.chr
when ?[
if nextchar() == ?: then
getchar()
@token = @token_str = '[:'
else
@token = @token_str = '['
end
when ?.
case nextchar()
when ?+, ?<, ?>, ?=, ?!
c = getchar()
if nextchar() == ?= then
getchar()
@token = @token_str = ".#{c.chr}="
else
@token = @token_str = ".#{c.chr}"
end
else
@token = @token_str = '.'
end
when ?!
if nextchar() == ?= then
getchar()
@token = @token_str = '!='
else
@token = @token_str = '!'
end
when ?<, ?>, ?=
case nextchar()
when ?\=
getchar()
@token = @token_str = ch.chr + '='
else
@token = @token_str = ch.chr
end
when ?+, ?-, ?*, ?/, ?%, ?^
if nextchar() == ?= then
getchar()
@token = @token_str = ch.chr + '='
else
@token = @token_str = ch.chr
end
when ?\\, ??, ?\, , ?"
@token = @token_str = ch.chr
when ?&, ?|
if nextchar() == ch then
getchar()
@token = @token_str = ch.chr + ch.chr
else
raise SyntaxError.new("invalid char: #{ch.chr}", self)
end
when ?@
s = ''
s << getchar() while word?(nextchar())
case s
when 'stag', 'cont', 'etag'
@token = s.intern
@token_str = s
else
@token = :expand2
@token_str = s
if s.empty? then
msg = "'@': macro name required."
raise SyntaxError.new(msg)
end
end
else
raise SyntaxError.new("invalid char: #{ch.chr}", self)
end
return @token
end
def scan_all
s = ''
while gettoken() != nil do
if @token == :name || @token == :number then
s << @token_str
elsif @token == :true || @token == :false || @token == :null || @token == :empty
s << @token_str
elsif @token == :string then
s << @token_str.inspect
elsif @token == :expand2 then
s << '@' + @token_str
elsif @token.is_a?(Symbol) then
s << @token.inspect
elsif @token == ':::' then
s << @token + @token_str
elsif @token == '::' then
s << @token + @token_str
else
s << @token
end
s << "\n"
end
return s
end
end
module Helper
def self.compile(pdata_str, plogic_str, lang, toppings)
compiler = Kwartz::Compiler.new(lang, toppings)
output = compiler.compile(pdata_str, plogic_str)
return output
end
def self.convert(pdata_str, toppings)
converter = Kwartz::DefaultConverter.new(pdata_str, toppings)
output = converter.convert()
return output
end
def self.translate(plogic_str, lang, toppings)
unless Kwartz::Translator.registered?(lang)
raise InvalidLanguageError.new(lang)
end
scanner = Kwartz::Scanner.new(plogic_str, toppings)
parser = Kwartz::Parser.new(scanner, toppings)
translator = Kwartz::Translator.instance(lang, toppings)
nodelist = parser.parse()
output = translator.translate_all(nodelist)
return output
end
def self.parse(plcode_str, toppings)
scanner = Kwartz::Scanner.new(plcode_str, toppings)
parser = Kwartz::Parser.new(scanner, toppings)
nodelist = parser.parse()
return nodelist
end
def self.parse_stmt(plcode_str, toppings)
scanner = Kwartz::Scanner.new(plcode_str, toppings)
parser = Kwartz::Parser.new(scanner, toppings)
nodelist = parser.parse()
output = nodelist.print_all()
return output
end
def self.parse_expr(expression_str, toppings)
scanner = Kwartz::Scanner.new(expression_str, toppings)
parser = Kwartz::Parser.new(scanner, toppings)
node = parser.parse_assignment()
if parser.token then
msg = ''
raise Kwartz::SyntaxError.new(msg, scanner)
end
output = node.print_all
return output
end
def self.scan(pdata_str, toppings)
scanner = Kwartz::Scanner.new(pdata_str, toppings)
output = scanner.scan_all()
return output
end
def self.delete_directives(input_str, attr_name='kd')
s = input_str.gsub(/\b#{attr_name}=(\".*?\"|[\-\:\#\@\w]+)/, '')
return s
end
def self.fetch(input_str)
converter = Kwartz::DefaultConverter.new(input_str, {})
converter.instance_eval {
def self.fetch
return _fetch()
end
}
s = ''
while fv = converter.fetch() do
s << fv.head_text.inspect << " + " << fv.tag_str.inspect << "\n"
end
return s
end
def self.analyze(pdata_str, plogic_str, toppings)
converter = Kwartz::DefaultConverter.new(pdata_str)
scanner = Kwartz::Scanner.new(converter.convert() + plogic_str)
parser = Kwartz::Parser.new(scanner)
nodelist = parser.parse()
analyzer = Kwartz::Analyzer.new(nodelist)
analyzer.analyze()
s = ''
analyzer.warnings.each do |message|
s << '*** warning: ' << message << "\n"
end
s << "global variables:"
analyzer.globals.each { |varname| s << ' ' << varname }
s << "\n"
s << "local variables: "
analyzer.locals.each { |varname| s << ' ' << varname }
s << "\n"
return s
end
def self.do_action(action, input, plogic, lang, toppings)
output = nil
case action
when 'compile'
output = self.compile(input, plogic, lang, toppings)
when 'convert'
output = self.convert(input, toppings)
when 'translate'
output = self.translate(input + plogic, lang, toppings)
when 'parse'
output = self.parse_stmt(input + plogic, toppings)
when 'scan'
output = self.scan(input + plogic, toppings)
when 'delete_directives'
attr_name = toppings[:attr_name] || 'kd'
output = self.delete_directives(input, attr_name)
when 'fetch'
output = self.fetch(input)
when 'analyze'
output = self.analyze(input, plogic, toppings)
end
return output
end
end
module Util
class CommandOptionError < StandardError
def initialize(msg)
super(msg)
end
end
def self.parse_argv(argv, single_options=nil, argneed_options=nil)
options = {}
toppings = {}
return options, toppings if !argv
opttypes = {}
single_options.each_byte do |ch|
opttypes[ch] = :single
end if single_options
argneed_options.each_byte do |ch|
opttypes[ch] = :arg_need
end if argneed_options
opttypes[?-] = :topping
while argv[0] && argv[0][0] == ?- do
optstr = argv.shift
optstr = optstr[1, optstr.length-1]
while optstr && !optstr.empty? do
optchar = optstr[0]
optstr[0] = ''
optstr = nil if optstr && optstr.empty?
case opttypes[optchar]
when :single
options[optchar] = true
when :arg_need
arg = optstr || argv.shift
raise CommandOptionError.new("-#{optchar.chr}: argument reguired.") unless arg
options[optchar] = arg
optstr = nil
when :topping
if optstr == 'help' then
options[?h] = true
elsif optstr =~ /^(\w+)(=.*)?/ then
key = $1.intern
value = $2
if !value || value.empty? then
value = true
else
value.sub!(/^=/, '')
value = str2value(value)
end
toppings[key] = value
end
optstr = nil
else
raise CommandOptionError.new("-#{optchar.chr}: invalid option.")
end
end
end
return options, toppings
end
def self.str2value(str)
case str
when /^\d+$/
value = str.to_i
when /^true$/i, /^yes$/i
value = true
when /^false$/i, /^no$/i
value = false
when /^nil$/, /^null$/i
value = nil
when /^\d+$/
value = str.to_i
when /^(\d*\.\d+|\d+\.\d*)$/
value = str.to_f
when /^\/(.*)\/$/
value = Regexp.new($1)
when /^'(.*)'$/
value = eval value
when /^"(.*)"$/
value = eval value
else
value = str
end
return value
end
end
end