module PETOOH

Public Instance Methods

parse(io) click to toggle source

reads PETOOH program from io and parses it into Array of PETOOH keywords (in the form of String-s).

# File gen/lib/petooh.rb, line 107
def parse(io)
  yy_parse(io)
end
run(program, debug = false) click to toggle source

program is an Array of PETOOH keywords (in the form of String-s).

debug - if true then PETOOH VM state is dumped on each execution step.

# File gen/lib/petooh.rb, line 13
def run(program, debug = false)
  # Init virtual machine.
  mem = [0] * 16
  data_ptr = 0
  pc = 0  # Index of current instruction in program.
  # Run!
  while pc < program.size
    # Log (if needed).
    if debug
      STDERR.puts "MEM: #{mem.join(" ")}"
      STDERR.puts "PC: #{pc} (#{program[pc]})"
      STDERR.puts "DP: #{data_ptr} (#{mem[data_ptr]})"
    end
    # Analyze current program instruction.
    case program[pc]
    when "Kudah"
      #
      data_ptr += 1
      # Expand memory if needed.
      if data_ptr >= mem.size
        mem.concat([0] * 16)
      end
      #
      pc += 1
    when "kudah"
      #
      data_ptr -= 1
      # Convert the machine's state from the form of
      #   { data_ptr = -1, mem = { -1:x, 0:y, 1:z, … } }
      # to the form of
      #   { data_ptr = 0, mem = { 0:x, 1:y, 2:z, … } }
      if data_ptr < 0
        mem.unshift(0)
        data_ptr = 0
      end
      #
      pc += 1
    when "Ko"
      mem[data_ptr] += 1
      pc += 1
    when "kO"
      mem[data_ptr] -= 1
      pc += 1
    when "Kukarek"
      print mem[data_ptr].chr
      pc += 1
    when "Kud"
      if mem[data_ptr] == 0
        # Increment PC until corresponding "kud" is encountered
        # (taking nested "Kud"/"kud" into account).
        nest_level = 1
        pc += 1
        while pc < program.size and nest_level > 0
          case program[pc]
          when "Kud"
            nest_level += 1
          when "kud"
            nest_level -= 1
          end
          pc += 1
        end
      else
        # Just skip the instruction.
        pc += 1
      end
    when "kud"
      if mem[data_ptr] != 0
        # Decrement PC until corresponding "Kud" is encountered
        # (taking nested "Kud"/"kud" into account).
        nest_level = 1
        pc -= 1
        while pc > 0 and nest_level > 0
          case program[pc]
          when "Kud"
            nest_level -= 1
          when "kud"
            nest_level += 1
          end
          pc -= 1
        end
        # Position PC right to the corresponding "Kud".
        pc += 1
      else
        # Just skip the instruction.
        pc += 1
      end
    end
  end
end

Private Instance Methods

yy_parse(input) click to toggle source

input is IO. It must have working IO#pos, IO#pos= and IO#set_encoding() methods.

It may raise YY_SyntaxError.

# File gen/lib/petooh.rb, line 121
def yy_parse(input)
  input.set_encoding("UTF-8", "UTF-8")
  context = YY_ParsingContext.new(input)
  yy_from_pcv(
    yy_nonterm1(context) ||
    # TODO: context.worst_error can not be nil here. Prove it.
    raise(context.worst_error)
  )
end