title: Simple interpreter incorrectly parses file
body: <p>Yesterday I've wrote interpreter for my new programming language, and I've put it on Github. Before this i made some simple tests and it seemed to work but now when i wanted to write some examples - it didn't work at all! I was really surprised, how did I get that output. For simple programs like this:</p>
  
  <pre><code>string Hello World!
  locate 0
  puts
  </code></pre>
  
  <p>It worked really well, displaying output 'Hello World!'. More complicated program looked like this:</p>
  
  <pre><code>ADD 49
  PUTCH
  SUB 1
  PUTCH
  MUL 2
  ADD 1
  PUTCH
  SUB 1
  DIV 2
  PUTCH
  LOCATE 2
  PUTD
  LOCATE 0
  SETV 10
  PUTCH
  SETV 0
  LOCATE 0
  STRING Hello World
  LOCATE 0
  PUTS
  SETV 10
  UNTILZERO
  {
  SUB 1
  }
  IFCC 10 == 10 {
  LOCATE 0
  SETV 0
  STRING Ok!
  LOCATE 0
  PUTS
  }
  </code></pre>
  
  <p><em>To understand this you need just some knowledge of Lua, C and Assembly.</em></p>
  
  <p>How to run code above: ./lua start.lua test.txt -gencode
  Output:</p>
  
  <pre><code>}UTSTE 0k! 10 {rld
  local tape = {}
  local pointer = 0
  }UTSTE 0k! 10 {rldpe[pointer] + 49
  </code></pre>
  
  <p><em>(I don't understand any part of this invaild output)</em></p>
  
  <p>So actually my code looks like this:</p>
  
  <pre><code>--[[
    ____            _        __            _      _  _   
   |  _ \          (_)      / _|          | |   _| || |_ 
   | |_) |_ __ __ _ _ _ __ | |_ _   _  ___| | _|_  __  _|
   |  _ &lt;| '__/ _` | | '_ \|  _| | | |/ __| |/ /_| || |_ 
   | |_) | | | (_| | | | | | | | |_| | (__|   &lt;|_  __  _|
   |____/|_|  \__,_|_|_| |_|_|  \__,_|\___|_|\_\ |_||_| 
   Brainfuck# v 1.0. Copyright (C) by Krzysztof Szewczyk.
   For more information check CONTRIB.MD and LICENSE.
   Code is licensed under GPLv3.
  --]]
  
  output = "local tape = {}\nlocal pointer = 0\n" --We will use Lua 'eval'-like function.
  brackets = 0
  
  -- Parse command with parameters 'params', and parameter number
  -- 'paramno'.
  function parse(command,params,paramno)
      if command == nil or params == nil or paramno == nil then return end
  
      local cmd = string.upper(command)
  
      if cmd == ";" then end
  
      if cmd == "ADD" then
          local amount = params[1]
          output = output .. "tape[pointer] = tape[pointer] + " .. amount .. "\n"
      end
  
      if cmd == "SUB" then
          local amount = params[1]
          output = output .. "tape[pointer] = tape[pointer] - " .. amount .. "\n"
      end
  
      if cmd == "MUL" then
          local amount = params[1]
          output = output .. "tape[pointer] = tape[pointer] * " .. amount .. "\n"
      end
  
      if cmd == "DIV" then
          local amount = params[1]
          if amount == 0 then
              print("[JIT] - Divide-by-zero error.")
          end
          output = output .. "tape[pointer] = tape[pointer] / " .. amount .. "\n"
      end
  
      if cmd == "ADDP" then
          local amount = params[1]
          output = output .. "pointer = pointer + " .. amount .. "\n"
      end
  
      if cmd == "SUBP" then
          local amount = params[1]
          output = output .. "pointer = pointer - " .. amount .. "\n"
      end
  
      if cmd == "MULP" then
          local amount = params[1]
          output = output .. "pointer = pointer * " .. amount .. "\n"
      end
  
      if cmd == "DIVP" then
          local amount = params[1]
          if amount == 0 then
              print("[JIT] - Divide-by-zero error.")
          end
          output = output .. "pointer = pointer / " .. amount .. "\n"
      end
  
      if cmd == "LOCATE" then
          local pos = params[1]
          output = output .. "pointer = " .. pos .. "\n"
      end
  
      if cmd == "SETV" then
          local val = params[1]
          output = output .. "tape[pointer] = " .. val .. "\n"
      end
  
      if cmd == "STRING" then
          local str = params[1]
          for i = 1, #str do
              local c = str:sub(i,i)
              output = output .. "tape[pointer] = string.byte(\"" .. c .. "\")\n"
              output = output .. "pointer = pointer + 1\n"
          end
          output = output .. "tape[pointer] = 0\n" --Remember to add null terminator (this can overwrite some of
                                                   --your crap stored in tape, so please have this in mind).
          output = output .. "pointer = pointer + 1\n"
      end
  
      if cmd == "PUTCH" then
          --Simply, no arguments
          output = output .. "io.write(string.char(tape[pointer]))\n"
      end
  
      if cmd == "PUTD" then
          --Simply, no arguments                                                                                            ^
          output = output .. "io.write(tape[pointer])\n" --Just print integer (as integer, not character, for character see |)
      end
  
      if cmd == "PUTS" then
          output = output .. "lastpntr=0\nwhile true do\nif tape[pointer] == 0 then break end\nio.write(string.char(tape[pointer]))\npointer = pointer + 1\nend\npointer=lastpntr\n" --I belive it's too complicated
                                                                                                                                                                                   --But it works.
      end
  
      if cmd == "GETCH" then
          output = output .. "tape[pointer] = io.read()\n" --HACK: Any raw input is not possible in multiplatform way.
      end
  
      if cmd == "UNTILZERO" then
          output = output .. "while tape[pointer]\n"
      end
  
      if cmd == "{" then
          output = output .. "do\n"
          brackets = brackets + 1;
      end
  
      if cmd == "}" then
          output = output .. "end\n"
          brackets = brackets - 1;
      end
  
      if cmd == "IUNTIL" then
          local type = params[1]
          local value = params[2]
          output = output .. "while tape[pointer] " .. type .. value .. "\n"
          brackets = brackets - 1;
      end
  
      if cmd == "TUNTIL" then
          local type = params[1]
          local value = params[2]
          output = output .. "while tape[pointer] " .. type .. "tape[" .. value .. "]" .. "\n"
          brackets = brackets - 1;
      end
  
      if cmd == "IFCC" then
          local val1 = params[1];
          local comp = params[2];
          local val2 = params[3];
          if params[4] == "{" then
              output = output .. "if " .. val1 .. comp .. val2 .. " then\n"
          else
              print("[JIT]: IFCC needs starting bracket at 4th argument. Please pass it and don't forget to close it.")
          end
      end
      if cmd == "IFCT" then
          local val1 = params[1];
          local comp = params[2];
          local val2 = params[3];
          if params[4] == "{" then
              output = output .. "if " .. val1 .. comp .. "tape[" .. val2 .. "] then\n"
          else
              print("[JIT]: IFCC needs starting bracket at 4th argument. Please pass it and don't forget to close it.")
          end
      end
  
      if cmd == "IFTT" then
          local val1 = params[1];
          local comp = params[2];
          local val2 = params[3];
          if params[4] == "{" then
              output = output .. "if tape[" .. val1 .. "]" .. comp .. "tape[" .. val2 .. "] then\n"
          else
              print("[JIT]: IFCC needs starting bracket at 4th argument. Please pass it and don't forget to close it.")
          end
      end
  
  end
  
  -- Function to split strings. Any questions?
  function string:split( inSplitPattern, outResults )
    if not outResults then
      outResults = { }
    end
    local theStart = 1
    local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
    while theSplitStart do
      table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
      theStart = theSplitEnd + 1
      theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
    end
    table.insert( outResults, string.sub( self, theStart ) )
    return outResults
  end
  
  -- I create new function to ensure that variables
  -- won't escape local context.
  function main(filename,gencodeswitch)
      local input = io.open(filename, "r")
      if input then
          --No error found while opening file
          while true do
              --First, read line.
              local line = input:read()
              --Now, let's check is it nil.
              --If so, we can break out of this loop.
              if line == nil then break end
              --Else, we need to parse this instruction.
              --So break it into main command and it's params.
              local space = string.find(line, " ") --Find first space occurence (to divide
                                                   --command from it's arguments).
              local params = string.sub(line, space+1) -- To get params just split string.
              local command = string.sub(line, 0, space-1) -- To get command without trailing space.
              --Actually, this space will get removed.
  
              local paramTable = params:split(",")
              local paramAmount = 0
  
              -- HACK: Looks like ineffective solution, but who cares?
              for i = 1, #paramTable do
                  paramAmount = paramAmount + 1;
              end
  
              print ("line:" .. line)
  
              parse(command,paramTable,paramAmount)
          end
          --Done parsing. Generate code
          if brackets ~= 0 then print("[JIT] Unbalanced brackets.") os.exit() end
          if gencodeswitch == "-gencode" then print(output) end
          --loadstring(output)()
      else
          --Oops, an error occured. Couldn't open file.
          print("[JIT]: Please pass vaild filename.")
          os.exit() --Bye, see ya later
      end
  end
  
  if arg[1] == nil then
      --User didn't pass any arguments.
      print("Brainfuck# v 1.0")
      print("Ussage:")
      print(".\lua start.lua &lt;input&gt; [-print]")
      print("Where:")
      print(".\lua - lua executable")
      print("start.lua - main module name");
      print("&lt;input&gt; - input filename (non-optional!)")
      print("[-print] - Optional, print source before execution.")
      os.exit();
  else
      --User passed an argument
      main(arg[1],arg[2])
  end
  </code></pre>
  
  <p>I can't find any errors but there must be a mistake. 
  If you want to see repo, <a href="https://github.com/KrzysztofSzewczyk/BrainfuckSharp" rel="nofollow noreferrer">here it is</a>, but it doesn't contain
  anything except license, readme, build and test scripts.
  I've put some comments to make understanding this broken code
  and trying to fixing it easier.</p>
  
  <p>Can anyone point me out where have I made a mistake?</p>