Class: Tcl::Ruby::Interpreter
- Inherits:
-
Object
- Object
- Tcl::Ruby::Interpreter
- Defined in:
- lib/tcl/ruby/util.rb,
lib/tcl/ruby/parser.rb,
lib/tcl/ruby/command.rb,
lib/tcl/ruby/commands/list.rb,
lib/tcl/ruby/commands/array.rb,
lib/tcl/ruby/commands/basic.rb
Instance Method Summary collapse
- #add_hook(name, &block) ⇒ Object
- #command(arg) ⇒ Object
- #delete_hook(name) ⇒ Object
- #exec_proc(arg, proc_info) ⇒ Object
-
#initialize ⇒ Interpreter
constructor
A new instance of Interpreter.
- #parse(str, to_list = false) ⇒ Object
- #replace(list) ⇒ Object
- #variables(arg) ⇒ Object
Constructor Details
#initialize ⇒ Interpreter
Returns a new instance of Interpreter.
4 5 6 7 8 9 10 |
# File 'lib/tcl/ruby/util.rb', line 4 def initialize @variables = {} @global = @variables @v_stack = [] @hooks = {} @proc = {} end |
Instance Method Details
#add_hook(name, &block) ⇒ Object
17 18 19 20 |
# File 'lib/tcl/ruby/util.rb', line 17 def add_hook(name, &block) raise(ArgumentError, 'block is not given') unless block_given? @hooks[name.to_s] = block end |
#command(arg) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/tcl/ruby/command.rb', line 4 def command(arg) return @prev if arg[0][0] == '#' # return previous command result when comment statement executed arg.map! { |e| replace(e) } arg.to_string name = arg[0] if @proc.key?(name) exec_proc(arg[1..-1], @proc[name]) elsif @hooks.key?(name) @hooks[name].call(arg[1..-1]) elsif respond_to?("___#{name}", true) @prev = send("___#{name}", arg[1..-1]) else raise(CommandError, "command not found, #{name}") end end |
#delete_hook(name) ⇒ Object
22 23 24 |
# File 'lib/tcl/ruby/util.rb', line 22 def delete_hook(name) @hooks.delete(name.to_s) end |
#exec_proc(arg, proc_info) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/tcl/ruby/command.rb', line 46 def exec_proc(arg, proc_info) proc_arg = parse(proc_info[0], true) raise(TclArgumentError, proc_arg.to_s) if proc_arg.size != arg.size @variables[:___global].each do |v| # FIXME: Buggy @global[v] = @variables[v] end if @variables.key?(:___global) @v_stack.push(@variables) @variables = {} arg.zip(proc_arg).each do |v| @variables[v[1]] = v[0] end ret = catch(:return) do parse(proc_info[1]) end @variables[:___global].each do |v| # FIXME: Buggy @global[v] = @variables[v] end if @variables.key?(:___global) @variables = @v_stack.pop ret end |
#parse(str, to_list = false) ⇒ Object
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 |
# File 'lib/tcl/ruby/parser.rb', line 6 def parse(str, to_list = false) s = StringScanner.new(str) r = ListArray.new pdepth = ddepth = bdepth = 0 buffer = '' ret = nil until s.empty? if s.scan(/\\./m) buffer << s[0] unless s[0][1] =~ /\s/ elsif !to_list && s.scan(/\r\n|\r|\n|;/) if pdepth == 0 && ddepth == 0 && bdepth == 0 r << buffer ret = command(r) unless r.empty? r = ListArray.new else buffer << s[0] end elsif s.scan(/\s+/) if pdepth == 0 && ddepth == 0 && bdepth == 0 r << buffer else buffer << s[0] end else buffer << if s.scan(/{/) # pdepth += 1 if ddepth == 0 pdepth += 1 if buffer == '' || pdepth != 0 s[0] elsif s.scan(/}/) ret = s[0] # pdepth -= 1 if ddepth == 0 pdepth -= 1 if pdepth != 0 raise(ParseError, 'extra characters after close-brace') if buffer[0] == '{' && pdepth == 0 && !s.check(/\s|\z/) ret elsif !to_list && s.scan(/\[/) bdepth += 1 if pdepth == 0 s[0] elsif !to_list && s.scan(/\]/) bdepth -= 1 if pdepth == 0 s[0] elsif s.scan(/"/) ret = s[0] ddepth = 1 - ddepth if buffer == '' || buffer[0] == '"' raise(ParseError, 'extra characters after close-quote') if buffer[0] == '"' && ddepth == 0 && !s.check(/\s|\z/) ret elsif s.scan(/\S/) s[0] else raise(ParseError, "parse error #{s.rest}") end end end r << buffer raise(ParseError, 'unmatched parenthesises') if ddepth != 0 || pdepth != 0 || bdepth != 0 if to_list r.to_string else ret = command(r) unless r.empty? ret end end |
#replace(list) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/tcl/ruby/command.rb', line 21 def replace(list) return list if list[0] == '{' # replace variable l = list.gsub(/\$\{(.+?)\}|\$([\w()]+)/) do v = Regexp.last_match(Regexp.last_match(1) ? 1 : 2) h = vv = nil if (m = v.match(/\((\w+)\)\z/)) h = m[1] vv = v v = vv.sub(/\((\w+)\)\z/, '') end raise(TclVariableNotFoundError, v.to_s, 'no such variable') unless @variables.key?(v) if h raise(TclVariableNotFoundError, vv.to_s, "variable isn't array") unless @variables[v].is_a?(Hash) @variables[v][h].to_s else raise(TclVariableNotFoundError, v.to_s, 'variable is array') if @variables[v].is_a?(Hash) @variables[v] end end # replace commands l = l.gsub(/\[(.+)\]/) { parse(Regexp.last_match(1)) } end |
#variables(arg) ⇒ Object
12 13 14 15 |
# File 'lib/tcl/ruby/util.rb', line 12 def variables(arg) raise(TclVariableNotFoundError, "can't read $#{arg}, no such variables") unless @variables.key?(arg) @variables[arg] end |