diff options
Diffstat (limited to 'test/racc/assets/intp.y')
-rw-r--r-- | test/racc/assets/intp.y | 546 |
1 files changed, 0 insertions, 546 deletions
diff --git a/test/racc/assets/intp.y b/test/racc/assets/intp.y deleted file mode 100644 index 39e42afd74..0000000000 --- a/test/racc/assets/intp.y +++ /dev/null @@ -1,546 +0,0 @@ -# -# intp -# - -class Intp::Parser - -prechigh - nonassoc UMINUS - left '*' '/' - left '+' '-' - nonassoc EQ -preclow - -rule - - program : stmt_list - { - result = RootNode.new( val[0] ) - } - - stmt_list : - { - result = [] - } - | stmt_list stmt EOL - { - result.push val[1] - } - | stmt_list EOL - - stmt : expr - | assign - | IDENT realprim - { - result = FuncallNode.new( @fname, val[0][0], - val[0][1], [val[1]] ) - } - | if_stmt - | while_stmt - | defun - - if_stmt : IF stmt THEN EOL stmt_list else_stmt END - { - result = IfNode.new( @fname, val[0][0], - val[1], val[4], val[5] ) - } - - else_stmt : ELSE EOL stmt_list - { - result = val[2] - } - | - { - result = nil - } - - while_stmt: WHILE stmt DO EOL stmt_list END - { - result = WhileNode.new(@fname, val[0][0], - val[1], val[4]) - } - - defun : DEF IDENT param EOL stmt_list END - { - result = DefNode.new(@fname, val[0][0], val[1][1], - Function.new(@fname, val[0][0], val[2], val[4])) - } - - param : '(' name_list ')' - { - result = val[1] - } - | '(' ')' - { - result = [] - } - | - { - result = [] - } - - name_list : IDENT - { - result = [ val[0][1] ] - } - | name_list ',' IDENT - { - result.push val[2][1] - } - - assign : IDENT '=' expr - { - result = AssignNode.new(@fname, val[0][0], val[0][1], val[2]) - } - - expr : expr '+' expr - { - result = FuncallNode.new(@fname, val[0].lineno, '+', [val[0], val[2]]) - } - | expr '-' expr - { - result = FuncallNode.new(@fname, val[0].lineno, '-', [val[0], val[2]]) - } - | expr '*' expr - { - result = FuncallNode.new(@fname, val[0].lineno, '*', [val[0], val[2]]) - } - | expr '/' expr - { - result = FuncallNode.new(@fname, val[0].lineno, - '/', [val[0], val[2]]) - } - | expr EQ expr - { - result = FuncallNode.new(@fname, val[0].lineno, '==', [val[0], val[2]]) - } - | primary - - primary : realprim - | '(' expr ')' - { - result = val[1] - } - | '-' expr =UMINUS - { - result = FuncallNode.new(@fname, val[0][0], '-@', [val[1]]) - } - - realprim : IDENT - { - result = VarRefNode.new(@fname, val[0][0], - val[0][1]) - } - | NUMBER - { - result = LiteralNode.new(@fname, *val[0]) - } - | STRING - { - result = StringNode.new(@fname, *val[0]) - } - | TRUE - { - result = LiteralNode.new(@fname, *val[0]) - } - | FALSE - { - result = LiteralNode.new(@fname, *val[0]) - } - | NIL - { - result = LiteralNode.new(@fname, *val[0]) - } - | funcall - - funcall : IDENT '(' args ')' - { - result = FuncallNode.new(@fname, val[0][0], val[0][1], val[2]) - } - | IDENT '(' ')' - { - result = FuncallNode.new(@fname, val[0][0], val[0][1], []) - } - - args : expr - { - result = val - } - | args ',' expr - { - result.push val[2] - } - -end - ----- header -# -# intp/parser.rb -# - ----- inner - - def initialize - @scope = {} - end - - RESERVED = { - 'if' => :IF, - 'else' => :ELSE, - 'while' => :WHILE, - 'then' => :THEN, - 'do' => :DO, - 'def' => :DEF, - 'true' => :TRUE, - 'false' => :FALSE, - 'nil' => :NIL, - 'end' => :END - } - - RESERVED_V = { - 'true' => true, - 'false' => false, - 'nil' => nil - } - - def parse(f, fname) - @q = [] - @fname = fname - lineno = 1 - f.each do |line| - line.strip! - until line.empty? - case line - when /\A\s+/, /\A\#.*/ - ; - when /\A[a-zA-Z_]\w*/ - word = $& - @q.push [(RESERVED[word] || :IDENT), - [lineno, RESERVED_V.key?(word) ? RESERVED_V[word] : word.intern]] - when /\A\d+/ - @q.push [:NUMBER, [lineno, $&.to_i]] - when /\A"(?:[^"\\]+|\\.)*"/, /\A'(?:[^'\\]+|\\.)*'/ - @q.push [:STRING, [lineno, eval($&)]] - when /\A==/ - @q.push [:EQ, [lineno, '==']] - when /\A./ - @q.push [$&, [lineno, $&]] - else - raise RuntimeError, 'must not happen' - end - line = $' - end - @q.push [:EOL, [lineno, nil]] - lineno += 1 - end - @q.push [false, '$'] - do_parse - end - - def next_token - @q.shift - end - - def on_error(t, v, values) - if v - line = v[0] - v = v[1] - else - line = 'last' - end - raise Racc::ParseError, "#{@fname}:#{line}: syntax error on #{v.inspect}" - end - ----- footer -# intp/node.rb - -module Intp - - class IntpError < StandardError; end - class IntpArgumentError < IntpError; end - - class Core - - def initialize - @ftab = {} - @obj = Object.new - @stack = [] - @stack.push Frame.new '(toplevel)' - end - - def frame - @stack[-1] - end - - def define_function(fname, node) - raise IntpError, "function #{fname} defined twice" if @ftab.key?(fname) - @ftab[fname] = node - end - - def call_function_or(fname, args) - call_intp_function_or(fname, args) { - call_ruby_toplevel_or(fname, args) { - yield - } - } - end - - def call_intp_function_or(fname, args) - if func = @ftab[fname] - frame = Frame.new(fname) - @stack.push frame - func.call self, frame, args - @stack.pop - else - yield - end - end - - def call_ruby_toplevel_or(fname, args) - if @obj.respond_to? fname, true - @obj.send fname, *args - else - yield - end - end - - end - - class Frame - - def initialize(fname) - @fname = fname - @lvars = {} - end - - attr :fname - - def lvar?(name) - @lvars.key? name - end - - def [](key) - @lvars[key] - end - - def []=(key, val) - @lvars[key] = val - end - - end - - - class Node - - def initialize(fname, lineno) - @filename = fname - @lineno = lineno - end - - attr_reader :filename - attr_reader :lineno - - def exec_list(intp, nodes) - v = nil - nodes.each {|i| v = i.evaluate(intp) } - v - end - - def intp_error!(msg) - raise IntpError, "in #{filename}:#{lineno}: #{msg}" - end - - def inspect - "#{self.class.name}/#{lineno}" - end - - end - - - class RootNode < Node - - def initialize(tree) - super nil, nil - @tree = tree - end - - def evaluate - exec_list Core.new, @tree - end - - end - - - class DefNode < Node - - def initialize(file, lineno, fname, func) - super file, lineno - @funcname = fname - @funcobj = func - end - - def evaluate(intp) - intp.define_function @funcname, @funcobj - end - - end - - class FuncallNode < Node - - def initialize(file, lineno, func, args) - super file, lineno - @funcname = func - @args = args - end - - def evaluate(intp) - args = @args.map {|i| i.evaluate intp } - begin - intp.call_intp_function_or(@funcname, args) { - if args.empty? or not args[0].respond_to?(@funcname) - intp.call_ruby_toplevel_or(@funcname, args) { - intp_error! "undefined function #{@funcname.id2name}" - } - else - recv = args.shift - recv.send @funcname, *args - end - } - rescue IntpArgumentError, ArgumentError - intp_error! $!.message - end - end - - end - - class Function < Node - - def initialize(file, lineno, params, body) - super file, lineno - @params = params - @body = body - end - - def call(intp, frame, args) - unless args.size == @params.size - raise IntpArgumentError, - "wrong # of arg for #{frame.fname}() (#{args.size} for #{@params.size})" - end - args.each_with_index do |v,i| - frame[@params[i]] = v - end - exec_list intp, @body - end - - end - - - class IfNode < Node - - def initialize(fname, lineno, cond, tstmt, fstmt) - super fname, lineno - @condition = cond - @tstmt = tstmt - @fstmt = fstmt - end - - def evaluate(intp) - if @condition.evaluate(intp) - exec_list intp, @tstmt - else - exec_list intp, @fstmt if @fstmt - end - end - - end - - class WhileNode < Node - - def initialize(fname, lineno, cond, body) - super fname, lineno - @condition = cond - @body = body - end - - def evaluate(intp) - while @condition.evaluate(intp) - exec_list intp, @body - end - end - - end - - - class AssignNode < Node - - def initialize(fname, lineno, vname, val) - super fname, lineno - @vname = vname - @val = val - end - - def evaluate(intp) - intp.frame[@vname] = @val.evaluate(intp) - end - - end - - class VarRefNode < Node - - def initialize(fname, lineno, vname) - super fname, lineno - @vname = vname - end - - def evaluate(intp) - if intp.frame.lvar?(@vname) - intp.frame[@vname] - else - intp.call_function_or(@vname, []) { - intp_error! "unknown method or local variable #{@vname.id2name}" - } - end - end - - end - - class StringNode < Node - - def initialize(fname, lineno, str) - super fname, lineno - @val = str - end - - def evaluate(intp) - @val.dup - end - - end - - class LiteralNode < Node - - def initialize(fname, lineno, val) - super fname, lineno - @val = val - end - - def evaluate(intp) - @val - end - - end - -end # module Intp - -begin - tree = nil - fname = 'src.intp' - File.open(fname) {|f| - tree = Intp::Parser.new.parse(f, fname) - } - tree.evaluate -rescue Racc::ParseError, Intp::IntpError, Errno::ENOENT - raise #### - $stderr.puts "#{File.basename $0}: #{$!}" - exit 1 -end |