function tokenize($line)
{
    $result = array();
    $start = 0;
    // states: start => whitespace
    //         ident => identifier / number etc.
    $state = 0;
    for ($i = 0; $i != strlen($line); $i++) {
        $char = $line[$i];
        if ($state == 0) {
            // start state
            if (isIdentifierChar($char)) {
                // identifier / number etc.
                $start = $i;
                $state = 1;
            } elseif (!isSpace($char)) {
                // operator
                $result[] = $char;
            }
        } else {
            // identifier state
            if (!isIdentifierChar($char)) {
                // end of identifier
                $state = 0;
                $result[] = substr($line, $start, $i - $start);
                if (!isSpace($char)) {
                    // additionally, the current char belongs to an operator
                    $result[] = $char;
                }
            }
        }
    }
    return $result;
}
 function _parse($s, $i, $U)
 {
     if ($i > $U) {
         return LOGO_OK;
     }
     $i--;
     while ($i <= $U) {
         $i++;
         if ($i > $U) {
             break;
         }
         /* Check if Time Out */
         $this->_endT = abs(round(microtime() - $this->_runningT, 5));
         if ($this->_endT > $this->_maxT) {
             $this->_getXY($s, $i + 1);
             $this->_src_line = __LINE__;
             return LOGO_ERROR_TIME_OUT;
         }
         /* Skip Spaces */
         if (isSpace($s[$i])) {
             continue;
         }
         /* Comments Start */
         if ($i + 1 < $U) {
             if ($s[$i] == '/' && $s[$i + 1] == '*') {
                 $i += 2;
                 while ($i + 1 < $U && !($s[$i] == '*' && $s[$i + 1] == '/')) {
                     $i++;
                 }
                 if ($i + 1 < $U && $s[$i] == '*' && $s[$i + 1] == '/') {
                     $i++;
                     continue;
                 } else {
                     $this->_getXY($s, $i);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_UNFINISHED_COMMENTS;
                 }
             }
             if ($s[$i] == '/' && $s[$i + 1] == '/') {
                 $i += 2;
                 while ($i < $U && $s[$i] != "\n") {
                     $i++;
                 }
                 if ($i < $U && $s[$i] == "\n") {
                     continue;
                 }
                 break;
             }
         }
         if ($s[$i] == ';' || $s[$i] == '#') {
             $i++;
             while ($i < $U && $s[$i] != "\n") {
                 $i++;
             }
             if ($i < $U && $s[$i] == "\n") {
                 continue;
             }
             break;
         }
         /* Coments Ends */
         /* Group */
         if (!$this->_inProc) {
             if ($s[$i] == '[') {
                 if (count($this->_coms) == 0) {
                     $this->_getXY($s, $i);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_UNKNOWN_GROUP;
                 }
                 $this->_repeat[] = $i;
                 //array_push($this->_repeat, $i);
                 continue;
             }
             if ($s[$i] == ']') {
                 if (count($this->_repeat) == 0) {
                     $this->_getXY($s, $i);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_TOO_MANY_RIGHT;
                 }
                 $groupstart = array_pop($this->_repeat);
                 if (count($this->_repeat) > 0) {
                     continue;
                 }
                 $k = array_pop($this->_coms);
                 if ($k == 'REPEAT') {
                     if (count($this->_repeatT) == 0) {
                         $this->_getXY($s, $i);
                         $this->_src_line = __LINE__;
                         return LOGO_ERROR_NO_REPEAT_TIME;
                     }
                     $lastRT = array_pop($this->_repeatT);
                     $t = 0;
                     for ($tt = 0; $tt < $lastRT; $tt++) {
                         $this->_vars->_setVar('REPCOUNT', $tt + 1);
                         $t = $this->_parse($s, $groupstart + 1, $i - 1);
                         if ($t != LOGO_OK && $t != LOGO_OK_PROC_RETURN) {
                             break;
                         }
                     }
                     if ($t == LOGO_OK_PROC_RETURN) {
                         if ($this->_rlvl == 0) {
                             $this->_rlvl = 1;
                             return $t;
                         }
                         continue;
                     }
                     if ($t == LOGO_OK) {
                         continue;
                     } else {
                         return $t;
                     }
                 } else {
                     if ($k == 'IF' || $k == 'FOREVER') {
                         if (count($this->_repeatT) == 0) {
                             $this->_getXY($s, $i);
                             $this->_src_line = __LINE__;
                             return LOGO_ERROR_MISSING_BOOLEAN;
                         }
                         $lastRT = array_pop($this->_repeatT);
                         if ($lastRT > 0) {
                             $lastRT = 1;
                         } else {
                             $lastRT = 0;
                         }
                         $t = 0;
                         if (strlen($k) == 2) {
                             if ($lastRT) {
                                 $t = $this->_parse($s, $groupstart + 1, $i - 1);
                             }
                         } else {
                             if ($lastRT) {
                                 //for (;;)
                                 //{
                                 $t = $this->_parse($s, $groupstart + 1, $i - 1);
                                 //if (($t!=LOGO_OK)&&($t!=LOGO_OK_PROC_RETURN)) break;
                                 //}
                                 // Not implemented in Web-version
                                 $this->_getXY($s, $i, $w);
                                 $this->_src_line = __LINE__;
                                 $this->pushWarn(LOGO_WARNING_NOT_FULLY_IMPLEMENTED, $this->_lineX, $this->_lineY, $k . ' ' . $w);
                             }
                         }
                         if ($t == LOGO_OK_PROC_RETURN) {
                             if ($this->_rlvl == 0) {
                                 $this->_rlvl = 1;
                                 return $t;
                             }
                             continue;
                         }
                         if ($t == LOGO_OK) {
                             continue;
                         } else {
                             return $t;
                         }
                     }
                 }
                 $this->_getXY($s, $i);
                 $this->_src_line = __LINE__;
                 return LOGO_ERROR_UNSUPPORTED_GROUP_ACTION;
             }
             /* Skip parsing until complete group statement */
             if (count($this->_repeat) > 0) {
                 continue;
             }
         }
         // Not _inProc
         /* Get a word */
         $w = strtoupper(LogoParser::getNextWord($s, $i, $U, $j));
         if (strlen($w) == 0) {
             break;
         }
         if ($this->_inProc) {
             if ($w == 'TO') {
                 $this->_getXY($s, $i);
                 $this->_src_line = __LINE__;
                 return LOGO_ERROR_NESTED_PROCEDURE_NOT_ALLOWED;
             } else {
                 if ($w == 'END') {
                     $this->_inProc = false;
                     $this->_to_end[] = $i - 1;
                     //array_push($this->_to_end,$i);
                     $i = $j;
                     $this->_to_counting_args = false;
                     continue;
                 } else {
                     if ($this->_to_counting_args) {
                         $ww = substr($w, 1);
                         if ($w[0] == ':' && $this->isGood($ww)) {
                             $counttoargs = count($this->_to_args);
                             if ($counttoargs == 0) {
                                 $this->_to_args[] = new Storage();
                                 $counttoargs = 0;
                             } else {
                                 $counttoargs--;
                             }
                             //$counttoargs = count($this->_to_args);
                             if ($this->_to_args[$counttoargs]->isVar($ww)) {
                                 $this->_getXY($s, $i);
                                 $this->_src_line = __LINE__;
                                 return LOGO_ERROR_REPEAT_PROC_ARG;
                             } else {
                                 $this->_to_args[$counttoargs]->_setVar($ww, 0);
                             }
                         } else {
                             $this->_to_counting_args = false;
                         }
                     }
                     $i = $j;
                     continue;
                 }
             }
         } else {
             if ($w == 'END') {
                 $this->_getXY($s, $i);
                 $this->_src_line = __LINE__;
                 return LOGO_ERROR_NO_TO;
             }
         }
         /*
                       if (count($this->_repeatT)>0)
                       {
                           if (($w=='REPEAT')||($w=='IF')||($w=='FOREVER'))
                           {
                               array_push($this->_repeatT,-1);
                           }
                           $i=$j;
                           continue;
                       }
         */
         if (count($this->_coms) > 0) {
             $k = array_pop($this->_coms);
             if ($k == 'TO') {
                 if (in_array($w, $this->_keywords) || in_array($w, $this->_keywords_args)) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_KEYWORD_IN_USE;
                 }
                 if (in_array($w, $this->_to_names)) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_PROC_DEFINED;
                 }
                 if (!LogoParser::isSymbol($w)) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_INVALID_SYMBOL;
                 }
                 if (count($this->_to_names) + 1 > $this->_maxProc) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_TOO_MANY_PROC;
                 }
                 $this->_inProc = true;
                 //array_push($this->_to_names, $w);
                 $this->_to_names[] = $w;
                 //array_push($this->_to_start, $i+strlen($w));
                 $this->_to_start[] = $i + strlen($w);
                 $this->_to_counting_args = true;
                 //array_push($this->_to_args, new Storage());
                 $this->_to_args[] = new Storage();
                 $i = $j;
                 continue;
             }
             //array_push($this->_coms, $k);
             $this->_coms[] = $k;
         }
         // Commands with at least one arg
         if (in_array($w, $this->_keywords_args)) {
             if (count($this->_coms) > 0) {
                 $this->_getXY($s, $i);
                 $this->_src_line = __LINE__;
                 return LOGO_ERROR_MISSING_ARG;
             }
             //array_push($this->_coms, $w);
             $this->_coms[] = $w;
             $i = $j;
             continue;
         }
         $procpos = array_search($w, $this->_to_names);
         if ($procpos !== false) {
             $argnum = $this->_to_args[$procpos]->getSize();
             if ($argnum > 0) {
                 //array_push($this->_coms, $w);
                 $this->_coms[] = $w;
                 $i = $j;
                 continue;
             }
             /* Procedure with no arguments */
             //array_push($this->_runningProc, $w);
             $this->_runningProc[] = $w;
             if (count($this->_runningProc) > $this->_maxProcLevel) {
                 $this->_getXY($s, $i, $w);
                 $this->_src_line = __LINE__;
                 return LOGO_ERROR_TOO_MANY_LEVELS;
             }
             //array_push($this->_var_stack, $this->_to_args[$procpos]);
             $this->_var_stack[] = clone $this->_to_args[$procpos];
             $this->removeLocalVars();
             $ret = $this->_parse($s, $this->_to_start[$procpos], $this->_to_end[$procpos]);
             $this->_to_args[$procpos] = array_pop($this->_var_stack);
             array_pop($this->_runningProc);
             if ($ret == LOGO_OK_PROC_RETURN) {
                 if ($this->_rlvl == 0) {
                     $this->_rlvl = 1;
                     return $ret;
                 }
                 $i = $j;
                 continue;
             }
             if ($ret == LOGO_OK || $ret == LOGO_OK_PROC_RETURN) {
                 $i = $j;
                 continue;
             } else {
                 return $ret;
             }
         }
         // Commands with no args
         if (in_array($w, $this->_keywords)) {
             if ($w == 'STOP') {
                 if ($this->_inProc || count($this->_runningProc) > 0) {
                     $this->_rlvl = 0;
                     return LOGO_OK_PROC_RETURN;
                 } else {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_STOP_NOT_IN_PROC;
                 }
             }
             if ($w == 'PU' || $w == 'PENUP') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->pu();
                 $i = $j;
                 continue;
             }
             if ($w == 'PE' || $w == 'PENERASER') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->pe();
                 $i = $j;
                 continue;
             }
             if ($w == 'PD' || $w == 'PENDOWN' || $w == 'PENNORMAL') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->pd();
                 $i = $j;
                 continue;
             }
             if ($w == 'ST' || $w == 'SHOWTURTLE') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->st();
                 $i = $j;
                 continue;
             }
             if ($w == 'DOT') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->dot();
                 $i = $j;
                 continue;
             }
             if ($w == 'FILL') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->fill();
                 $i = $j;
                 continue;
             }
             if ($w == 'HOME') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->home();
                 $this->_vars->_setVar('POSX', $this->_logo->getX());
                 $this->_vars->_setVar('POSY', $this->_logo->getY());
                 $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                 $i = $j;
                 continue;
             }
             if ($w == 'HT' || $w == 'HIDETURTLE') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 $this->_logo->ht();
                 $i = $j;
                 continue;
             }
             if ($w == 'WINDOW' || $w == 'FENCE' || $w == 'WRAP') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 if ($w[1] == 'I') {
                     $this->_logo->setWrap(LOGO_WINDOW);
                 } else {
                     if ($w[1] == 'E') {
                         $this->_logo->setWrap(LOGO_FENCE);
                     } else {
                         $this->_logo->setWrap(LOGO_WRAP);
                     }
                 }
                 $this->_vars->_setVar('POSX', $this->_logo->getX());
                 $this->_vars->_setVar('POSY', $this->_logo->getY());
                 $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                 $i = $j;
                 continue;
             }
             if ($w == 'CS' || $w == 'CLEANSCREEN' || $w == 'CLEAR') {
                 if (count($this->_coms) > 0) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
                 if (strlen($w) == 5) {
                     $this->_logo->clear();
                 } else {
                     $this->_logo->cs();
                     $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                     $this->_vars->_setVar('POSX', $this->_logo->getX());
                     $this->_vars->_setVar('POSY', $this->_logo->getY());
                 }
                 /*
                 $this->_getXY($s, $i, $w);
                 $this->_src_line=__LINE__;
                 $this->pushWarn( LOGO_WARNING_NOT_FULLY_IMPLEMENTED,
                 $this->_lineX,
                 $this->_lineY,
                 $w
                 );
                 */
                 $i = $j;
                 continue;
             }
         }
         // end of Commands with no args
         if (count($this->_coms) > 0) {
             $k = array_pop($this->_coms);
             if ($k == 'LOCAL') {
                 if ($w[0] != '"') {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MAKE_NEED_QUOTE;
                 }
                 $ww = substr($w, 1);
                 if (!$this->isGood($ww)) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MAKE_INVALID_NAME;
                 }
                 if (!($this->_inProc || count($this->_runningProc) > 0)) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     $this->pushWarn(LOGO_WARNING_LOCAL_MAKE_GLOBALUSE, $this->_lineX, $this->_lineY, $w);
                 } else {
                     $counttoargs = count($this->_runningProc);
                     if ($counttoargs > 0) {
                         //array_push($this->_localmake, array($this->_runningProc[$counttoargs-1],$ww));
                         $this->_localmake[] = array($this->_runningProc[$counttoargs - 1], $ww);
                     }
                 }
                 $i = $j;
                 continue;
             } else {
                 if ($k == 'MAKE' || $k == 'LOCALMAKE') {
                     if (count($this->_args) == 0) {
                         if ($w[0] != '"') {
                             $this->_getXY($s, $i, $w);
                             $this->_src_line = __LINE__;
                             return LOGO_ERROR_MAKE_NEED_QUOTE;
                         }
                         $ww = substr($w, 1);
                         if (!$this->isGood($ww)) {
                             $this->_getXY($s, $i, $w);
                             $this->_src_line = __LINE__;
                             return LOGO_ERROR_MAKE_INVALID_NAME;
                         }
                         //array_push($this->_coms, $k);
                         $this->_coms[] = $k;
                         //array_push($this->_args, $ww);
                         $this->_args[] = $ww;
                         $i = $j;
                         continue;
                     } else {
                         $t = array_pop($this->_args);
                         if ($w[0] == "\"") {
                             $ww = substr($w, 1);
                             if ($k == 'MAKE') {
                                 $this->_makevars->_setVar($t, $ww);
                                 $i = $j;
                                 continue;
                             } else {
                                 if (!($this->_inProc || count($this->_runningProc) > 0)) {
                                     $this->_getXY($s, $i, $w);
                                     $this->_src_line = __LINE__;
                                     $this->pushWarn(LOGO_WARNING_LOCAL_MAKE_GLOBALUSE, $this->_lineX, $this->_lineY, $w);
                                     $this->_makevars->_setVar($t, $ww);
                                     $i = $j;
                                     continue;
                                 } else {
                                     $counttoargs = count($this->_runningProc);
                                     if ($counttoargs > 0) {
                                         //array_push($this->_localmake, array(
                                         //$this->_runningProc[$counttoargs-1],
                                         //$t
                                         //));
                                         $this->_localmake[] = array($this->_runningProc[$counttoargs - 1], $t);
                                         $procpos = array_search($this->_runningProc[$counttoargs - 1], $this->_to_names);
                                         if ($procpos !== false) {
                                             $this->_to_args[$procpos]->_setVar($t, $ww);
                                         }
                                         $i = $j;
                                         continue;
                                     }
                                 }
                             }
                         } else {
                             if ($this->isNumber($w, $_real, $value)) {
                                 if ($k == 'MAKE') {
                                     $this->_makevars->_setVar($t, $value);
                                     $i = $j;
                                     continue;
                                 } else {
                                     if (!($this->_inProc || count($this->_runningProc) > 0)) {
                                         $this->_getXY($s, $i, $w);
                                         $this->_src_line = __LINE__;
                                         $this->pushWarn(LOGO_WARNING_LOCAL_MAKE_GLOBALUSE, $this->_lineX, $this->_lineY, $w);
                                         $this->_makevars->_setVar($t, $value);
                                         $i = $j;
                                         continue;
                                     } else {
                                         $counttoargs = count($this->_runningProc);
                                         if ($counttoargs > 0) {
                                             $this->_localmake[] = array($this->_runningProc[$counttoargs - 1], $t);
                                             $procpos = array_search($this->_runningProc[$counttoargs - 1], $this->_to_names);
                                             if ($procpos !== false) {
                                                 $this->_to_args[$procpos]->_setVar($t, $value);
                                             }
                                             $i = $j;
                                             continue;
                                         }
                                     }
                                 }
                             } else {
                                 $this->_getXY($s, $i, $w);
                                 $this->_src_line = __LINE__;
                                 return LOGO_ERROR_MAKE_INVALID_VALUE;
                             }
                         }
                     }
                 }
             }
             // end of make, local make
             //array_push($this->_coms, $k);
             $this->_coms[] = $k;
         }
         if ($this->isNumber($w, $realnum, $value)) {
             if (count($this->_coms) == 0) {
                 $this->_getXY($s, $i, $w);
                 $this->_src_line = __LINE__;
                 return LOGO_ERROR_MISSING_COMMAND;
             }
             /*
             if ($realnum)
             {
                 $this->_getXY($s, $i, $w);
                 $this->_src_line=__LINE__;
                 $this->pushWarn( LOGO_WARNING_NUMBER_ROUNDED,
                 $this->_lineX,
                 $this->_lineY,
                 $w
                 );
             }
             */
             $k = array_pop($this->_coms);
             $procpos = array_search($k, $this->_to_names);
             if ($procpos !== false) {
                 $argnum = $this->_to_args[$procpos]->getSize();
                 if ($argnum > count($this->_args) + 1) {
                     //array_push($this->_coms, $k);
                     $this->_coms[] = $k;
                     //array_push($this->_args, $w);
                     $this->_args[] = $w;
                     $i = $j;
                     continue;
                 }
                 //array_push($this->_args, $w);
                 $this->_args[] = $w;
                 $u = 0;
                 //array_push($this->_var_stack, $this->_to_args[$procpos]);
                 $this->_var_stack[] = clone $this->_to_args[$procpos];
                 $this->removeLocalVars();
                 $varlist = $this->_to_args[$procpos]->keys();
                 foreach ($varlist as $key) {
                     $this->isNumber($this->_args[$u++], $real, $value);
                     $this->_to_args[$procpos]->_setVar($key, $value);
                 }
                 $usa = $this->_to_start[$procpos] + 1;
                 for ($sk = 0; $sk < $argnum; $sk++) {
                     $t = LogoParser::getNextWord($s, $usa, $this->_to_end[$procpos], $usa);
                     $usa++;
                 }
                 //array_push($this->_runningProc, $k);
                 $this->_runningProc[] = $k;
                 if (count($this->_runningProc) > $this->_maxProcLevel) {
                     $this->_getXY($s, $i, $w);
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_TOO_MANY_LEVELS;
                 }
                 for (; $u > 0; $u--) {
                     array_pop($this->_args);
                 }
                 // recursion
                 $ret = false;
                 $ret = $this->_parse($s, $usa, $this->_to_end[$procpos]);
                 $this->_to_args[$procpos] = array_pop($this->_var_stack);
                 array_pop($this->_runningProc);
                 if ($ret == LOGO_OK_PROC_RETURN) {
                     if ($this->_rlvl == 0) {
                         $this->_rlvl = 1;
                         return $ret;
                     }
                     $i = $j;
                     continue;
                 }
                 if ($ret == LOGO_OK || $ret == LOGO_OK_PROC_RETURN) {
                     $i = $j;
                     continue;
                 } else {
                     return $ret;
                 }
             } else {
                 if ($k == 'BK' || $k == 'BACK' || $k == 'FD' || $k == 'FORWARD' || $k == 'WALK' || $k == 'JUMP' || $k == 'JMP') {
                     if ($this->_logo->isWrap() == LOGO_FENCE) {
                         $x1 = $this->_logo->getX();
                         $y1 = $this->_logo->getY();
                         $x2 = round($x1 + $value * sin($this->_logo->getD() * 0.017453292519943295));
                         $y2 = round($y1 - $value * cos($this->_logo->getD() * 0.017453292519943295));
                         if ($this->_logo->isOutXY($x2, $y2)) {
                             $this->_getXY($s, $i, $w);
                             $this->_src_line = __LINE__;
                             $this->pushWarn(LOGO_WARNING_TURTLE_OUT, $this->_lineX, $this->_lineY, $w);
                         }
                     }
                     if ($k[0] == 'J') {
                         $this->_logo->jump($value);
                     } else {
                         if ($k[0] == 'B') {
                             $this->_logo->fd(-$value);
                         } else {
                             $this->_logo->fd($value);
                         }
                     }
                     $this->_vars->_setVar('POSX', $this->_logo->getX());
                     $this->_vars->_setVar('POSY', $this->_logo->getY());
                 } else {
                     if ($k == 'RT' || $k == 'RIGHT' || $k == 'TURN') {
                         $this->_logo->rt($value);
                         $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                     } else {
                         if ($k == 'LT' || $k == 'LEFT') {
                             $this->_logo->lt($value);
                             $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                         } else {
                             if ($k == 'SETPC' || $k == 'SETPENCOLOR' || $k == 'SETPENCOLOUR') {
                                 $value = (int) $value;
                                 if ($value >= 0 && $value <= 15) {
                                     $this->_logo->setPCrgb($this->Logo_Color_R[$value], $this->Logo_Color_G[$value], $this->Logo_Color_B[$value]);
                                 } else {
                                     if ($this->_istruecolor) {
                                         $this->_logo->setPC($value);
                                     } else {
                                         $this->_src_line = __LINE__;
                                         $this->pushWarn(LOGO_WARNING_UNSUPPORTED_COLOR, $this->_lineX, $this->_lineY, $w);
                                     }
                                 }
                                 $this->_vars->_setVar('PENCOLOR', $value);
                                 $this->_vars->_setVar('PENCOLOUR', $value);
                             } else {
                                 if ($k == 'SETFC' || $k == 'SETFLOODCOLOR' || $k == 'SETFLOODCOLOUR') {
                                     $value = (int) $value;
                                     if ($value >= 0 && $value <= 15) {
                                         $this->_logo->setFCrgb($this->Logo_Color_R[$value], $this->Logo_Color_G[$value], $this->Logo_Color_B[$value]);
                                     } else {
                                         if ($this->_istruecolor) {
                                             $this->_logo->setFC($value);
                                         } else {
                                             $this->_src_line = __LINE__;
                                             $this->pushWarn(LOGO_WARNING_UNSUPPORTED_COLOR, $this->_lineX, $this->_lineY, $w);
                                         }
                                     }
                                     $this->_vars->_setVar('FLOODCOLOR', $value);
                                     $this->_vars->_setVar('FLOODCOLOUR', $value);
                                 } else {
                                     if ($k == 'SETSC' || $k == 'SETSCREENCOLOR' || $k == 'SETSCREENCOLOUR') {
                                         $this->_getXY($s, $i, $w);
                                         $this->_src_line = __LINE__;
                                         $this->pushWarn(LOGO_WARNING_UNSUPPORTED_BG_CHANGE, $this->_lineX, $this->_lineY, $w);
                                         if ($value >= 0 && $value <= 15) {
                                             $this->_logo->setSCrgb($this->Logo_Color_R[$value], $this->Logo_Color_G[$value], $this->Logo_Color_B[$value]);
                                         } else {
                                             if ($this->_istruecolor) {
                                                 $this->_logo->setSC($value);
                                             } else {
                                                 $this->_src_line = __LINE__;
                                                 $this->pushWarn(LOGO_WARNING_UNSUPPORTED_COLOR, $this->_lineX, $this->_lineY, $w);
                                             }
                                         }
                                         $this->_vars->_setVar('SCREENCOLOR', $value);
                                         $this->_vars->_setVar('SCREENCOLOUR', $value);
                                     } else {
                                         if ($k == 'REPEAT' || $k == 'IF' || $k == 'FOREVER') {
                                             //array_push($this->_repeatT, round($value));
                                             $this->_repeatT[] = round($value);
                                             //array_push($this->_coms, $k);
                                             $this->_coms[] = $k;
                                         } else {
                                             if ($k == 'SETXY' || $k == 'SETPOS') {
                                                 if (count($this->_args) == 0) {
                                                     //array_push($this->_coms, $k);
                                                     $this->_coms[] = $k;
                                                     //array_push($this->_args, $value);
                                                     $this->_args[] = $value;
                                                 } else {
                                                     $t = array_pop($this->_args);
                                                     $this->_logo->lineTo($t, -$value, true);
                                                     if ($this->_logo->isWrap() == LOGO_FENCE) {
                                                         if ($this->_logo->isOutXY($t, -$value)) {
                                                             $this->_getXY($s, $i, $w);
                                                             $this->_src_line = __LINE__;
                                                             $this->pushWarn(LOGO_WARNING_TURTLE_OUT, $this->_lineX, $this->_lineY, $w);
                                                         }
                                                     }
                                                 }
                                                 $this->_vars->_setVar('POSX', $this->_logo->getX());
                                                 $this->_vars->_setVar('POSY', $this->_logo->getY());
                                             } else {
                                                 if ($k == 'ARC' || $k == 'ARC2') {
                                                     if (count($this->_args) == 0) {
                                                         //array_push($this->_coms, $k);
                                                         $this->_coms[] = $k;
                                                         //array_push($this->_args, $value);
                                                         $this->_args[] = $value;
                                                     } else {
                                                         $t = array_pop($this->_args);
                                                         $this->_logo->arc($t, $value);
                                                     }
                                                 } else {
                                                     if ($k == 'DOTXY') {
                                                         if (count($this->_args) == 0) {
                                                             //array_push($this->_coms, $k);
                                                             $this->_coms[] = $k;
                                                             //array_push($this->_args, $value);
                                                             $this->_args[] = $value;
                                                         } else {
                                                             $t = array_pop($this->_args);
                                                             $this->_logo->dotxy($t, -$value);
                                                         }
                                                     } else {
                                                         if ($k == 'SLEEP' || $k == 'PRINT' || $k == 'IMGW' || $k == 'IMGH' || $k == 'WAIT' || $k == 'FOREVER') {
                                                             // Not implemented in Web-version
                                                             $this->_getXY($s, $i, $w);
                                                             $this->_src_line = __LINE__;
                                                             $this->pushWarn(LOGO_WARNING_NOT_FULLY_IMPLEMENTED, $this->_lineX, $this->_lineY, $k . ' ' . $w);
                                                         } else {
                                                             if ($k == 'SETA') {
                                                                 $this->_logo->setD($value);
                                                                 $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                                                             } else {
                                                                 if ($k == 'SETX') {
                                                                     $this->_logo->lineTo($value, $this->_logo->getY(), true);
                                                                     if ($this->_logo->isWrap() == LOGO_FENCE) {
                                                                         if ($value > $this->_logo->getImageHX() || $value < -$this->_logo->getImageHX()) {
                                                                             $this->_getXY($s, $i, $w);
                                                                             $this->_src_line = __LINE__;
                                                                             $this->pushWarn(LOGO_WARNING_TURTLE_OUT, $this->_lineX, $this->_lineY, $w);
                                                                         }
                                                                     }
                                                                     $this->_vars->_setVar('POSX', $this->_logo->getX());
                                                                     $this->_vars->_setVar('POSY', $this->_logo->getY());
                                                                 } else {
                                                                     if ($k == 'SETY') {
                                                                         $this->_logo->lineTo($this->_logo->getX(), -$value, true);
                                                                         if ($this->_logo->isWrap() == LOGO_FENCE) {
                                                                             if (-$value > $this->_logo->getImageHY() || -$value < -$this->_logo->getImageHY()) {
                                                                                 $this->_getXY($s, $i, $w);
                                                                                 $this->_src_line = __LINE__;
                                                                                 $this->pushWarn(LOGO_WARNING_TURTLE_OUT, $this->_lineX, $this->_lineY, $w);
                                                                             }
                                                                         }
                                                                         $this->_vars->_setVar('POSX', $this->_logo->getX());
                                                                         $this->_vars->_setVar('POSY', $this->_logo->getY());
                                                                     } else {
                                                                         if ($k == 'TO') {
                                                                             $this->_getXY($s, $i, $w);
                                                                             $this->_src_line = __LINE__;
                                                                             return LOGO_ERROR_INVALID_PROC_NAME;
                                                                         } else {
                                                                             if (($procpos = array_search($w, $this->_to_names)) !== false) {
                                                                                 $argnum = $this->_to_args[$procpos]->getSize();
                                                                                 if ($argnum > 0) {
                                                                                     //array_push($this->_coms, $w);
                                                                                     $this->_coms[] = $w;
                                                                                     $i = $j;
                                                                                     continue;
                                                                                 }
                                                                                 //array_push($this->_runningProc, $w);
                                                                                 $this->_runningProc[] = $w;
                                                                                 if (count($this->_runningProc) > $this->_maxProcLevel) {
                                                                                     $this->_getXY($s, $i, $w);
                                                                                     $this->_src_line = __LINE__;
                                                                                     return LOGO_ERROR_TOO_MANY_LEVELS;
                                                                                 }
                                                                                 //array_push($this->_var_stack, $this->_to_args[$procpos]);
                                                                                 $this->_var_stack[] = clone $this->_to_args[$procpos];
                                                                                 $this->removeLocalVars();
                                                                                 $ret = $this->_parse($s, $this->_to_start[$procpos], $this->_to_end[$procpos]);
                                                                                 $this->_to_args[$procpos] = array_pop($this->_var_stack);
                                                                                 array_pop($this->_runningProc);
                                                                                 if ($ret == LOGO_OK_PROC_RETURN) {
                                                                                     if ($this->_rlvl == 0) {
                                                                                         $this->_rlvl = 1;
                                                                                         return $ret;
                                                                                     }
                                                                                     $i = $j;
                                                                                     continue;
                                                                                 }
                                                                                 if ($ret == LOGO_OK || $ret == LOGO_OK_PROC_RETURN) {
                                                                                     $i = $j;
                                                                                     continue;
                                                                                 } else {
                                                                                     return $ret;
                                                                                 }
                                                                             }
                                                                         }
                                                                     }
                                                                 }
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             $i = $j;
             continue;
         }
         // end of isNumber
         /* The word is Not Recongized */
         if ($w) {
             $this->_getXY($s, $i, $w);
             $this->_src_line = __LINE__;
             return LOGO_ERROR_BAD_COMMAND;
         }
     }
     // end of processing
     /* Error Handling */
     $this->_getXY($s, $U);
     if ($this->_inProc) {
         $this->_src_line = __LINE__;
         return LOGO_ERROR_END_NOT_FOUND;
     } else {
         if (count($this->_repeat) > 0) {
             $this->_src_line = __LINE__;
             return LOGO_ERROR_TOO_MANY_LEFT;
         } else {
             if (count($this->_repeatT) > 0) {
                 $this->_getXY($s, $i);
                 $this->_src_line = __LINE__;
                 $this->pushWarn(LOGO_WARNING_MISSING_REPEAT_BODY, $this->_lineX, $this->_lineY, '');
             } else {
                 if (count($this->_coms) > 0) {
                     $this->_src_line = __LINE__;
                     return LOGO_ERROR_MISSING_ARG;
                 }
             }
         }
     }
     // Return OK
     return LOGO_OK;
 }