Login   Register  
PHP Classes
elePHPant
Icontem

File: class.logo.parser.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Dr Zhihua Lai  >  Logo Interpreter  >  class.logo.parser.php  >  Download  
File: class.logo.parser.php
Role: Class source
Content type: text/plain
Description: Logo Interpreter Class
Class: Logo Interpreter
Logo language interpreter
Author: By
Last change: v0.2 released
Date: 2 years ago
Size: 67,923 bytes
 

Contents

Class file image Download
<?php

  // License: GNU General Public License (GPL) 
  // class.logo.parser.php
  // @ver 0.1

  // Author: Dr Zhihua Lai
  // Example URL: http://www.zhihua-lai.com/?do=Software.Logo

  error_reporting(E_ALL);

  // Define Directory
  define('LOGO_DIR', dirname(__FILE__).'/');
  
  // Include
  include(LOGO_DIR.'logo.php');
  require_once(LOGO_DIR.'util.php');
  require_once(LOGO_DIR.'class.storage.php');
  
  // Constants
  define('LOGO_OK_PROC_RETURN',-1);
  define('LOGO_OK',0);
  define('LOGO_ERROR_UNFINISHED_COMMENTS',1);
  define('LOGO_ERROR_MISSING_COMMAND',2);
  define('LOGO_WARNING_NOT_FULLY_IMPLEMENTED',3);
  define('LOGO_WARNING_NUMBER_ROUNDED',4);
  define('LOGO_ERROR_MISSING_ARG',5);
  define('LOGO_ERROR_BAD_COMMAND',6);
  define('LOGO_WARNING_UNSUPPORTED_BG_CHANGE',7);
  define('LOGO_ERROR_NO_REPEAT_TIME',8);
  define('LOGO_ERROR_UNSUPPORTED_GROUP_ACTION',9);
  define('LOGO_ERROR_TOO_MANY_LEFT',10);
  define('LOGO_ERROR_TOO_MANY_RIGHT',11);
  define('LOGO_INFORMATION_TOO_MANY_WARNING',12);
  define('LOGO_ERROR_TIME_OUT',13);
  define('LOGO_WARNING_MISSING_REPEAT_BODY',14);
  define('LOGO_ERROR_STOP_NOT_IN_PROC',15);
  define('LOGO_ERROR_END_NOT_FOUND',16);
  define('LOGO_ERROR_KEYWORD_IN_USE',17);
  define('LOGO_ERROR_NESTED_PROCEDURE_NOT_ALLOWED',18);
  define('LOGO_ERROR_INVALID_PROC_NAME',19);
  define('LOGO_ERROR_PROC_DEFINED',20);
  define('LOGO_ERROR_NO_TO',21);
  define('LOGO_ERROR_INVALID_SYMBOL',22);
  define('LOGO_ERROR_TOO_MANY_PROC',23);
  define('LOGO_WARNING_TURTLE_OUT',24);
  define('LOGO_ERROR_REPEAT_PROC_ARG',25);
  define('LOGO_ERROR_TOO_MANY_LEVELS',26);
  define('LOGO_WARNING_LOCAL_MAKE_GLOBALUSE',27);
  define('LOGO_ERROR_MAKE_NEED_QUOTE',28);
  define('LOGO_ERROR_MAKE_INVALID_NAME',29);
  define('LOGO_ERROR_MAKE_INVALID_VALUE',30);
  define('LOGO_ERROR_UNKNOWN_GROUP',31);
  define('LOGO_ERROR_MISSING_BOOLEAN',32);
  define('LOGO_WARNING_UNSUPPORTED_COLOR',33);
  
  class LogoParser
  {
      var $_logo;
      var $_s;
      var $_vars;
      var $_makevars;
      var $_localmake=array();
      var $_coms=array();
      var $_args=array();
      var $_lineX;
      var $_lineY;
      var $_warnings=array();
      var $_lineW;
      var $_maxW;
      var $_repeat=array();
      var $_repeatT=array();
      var $_maxT;
      var $_runningT;
      var $_maxProcLevel;
      var $_endT;
      var $_maxProc;
      var $_inProc;
      var $_rlvl;
      var $_to_names=array();
      var $_to_start=array();
      var $_to_end=array();
      var $_to_args=array();
      var $_to_counting_args;
      var $_var_stack=array();
      var $_src_line;
      var $_istruecolor;      
      var $_runningProc=array();      
      var $Logo_Color_R=array(0,0,0,0,255,255,165,211,153,173,127,224,250,221,255,255);
      var $Logo_Color_G=array(0,0,255,255,0,0,42,211,153,216,255,255,128,221,255,255);
      var $Logo_Color_B=array(0,255,0,255,0,255,42,211,153,230,212,255,114,221,0,255);      
      var $_keywords_args=array(
      'FORWARD','FD', 'WALK', 'JUMP', 'TURN', 'JMP',
      'BACK','BK',
      'RIGHT','RT',
      'LEFT','LT',
      'SETPC','SETPENCOLOR','SETPENCOLOUR',
      'SETSCREENCOLOR','SETSC','SETSCREENCOLOUR',
      'REPEAT',
      'SETXY','SETPOS','DOTXY',
      'SETX',
      'SETY',
      'SLEEP',
      'WAIT',
      'IMGW',
      'IMGH',
      'PRINT',
      'TO',
      'ARC','ARC2',
      'MAKE',
      'LOCALMAKE',
      'LOCAL',
      'IF',
      //'IFELSE',
      'SETFC','SETFLOODCOLOR','SETFLOODCOLOUR'
      );      
      var $_keywords=array(
      'HT','HIDETURTLE',
      'ST','SHOWTURTLE',
      'PU','PENUP',
      'PE','PENERASER',
      'PD','PENDOWN','PENNORMAL',
      'CS','CLEANSCREEN',
      'HOME',
      'FENCE',
      'WINDOW',
      'WRAP',
      'FILL',
      'END',
      'STOP',
      'DOT'
      );
      /* Constructor */
      function LogoParser(&$lgo, $s='')
      {
          $this->_logo=&$lgo;
          $this->_lineX=0;
          $this->_lineY=0;
          $this->_lineW='';
          $this->_maxW=25;
          $this->_maxT=3;
          $this->_maxProcLevel=999;
          $this->_maxProc=999;
          $this->_inProc=false;
          $this->_rlvl=0;
          $this->_to_counting_args=false;
          $this->_makevars=new Storage();
          $this->_vars=new Storage();
          $this->_vars->_setVar('REPCOUNT',0);
          $this->_vars->_setVar('SCREENCOLOUR',($lgo->getSC()));
          $this->_vars->_setVar('FLOODCOLOUR',($lgo->getFC()));
          $this->_vars->_setVar('PENCOLOUR',($lgo->getPC()));
          $this->_vars->_setVar('SCREENCOLOR',($lgo->getSC()));
          $this->_vars->_setVar('FLOODCOLOR',($lgo->getFC()));
          $this->_vars->_setVar('PENCOLOR',($lgo->getPC()));
          $this->_vars->_setVar('PI',pi());
          $this->_vars->_setVar('WIDTH', $lgo->getImageX());
          $this->_vars->_setVar('HEIGHT', $lgo->getImageY());
          $this->_vars->_setVar('MAXX', $lgo->getImageHX());
          $this->_vars->_setVar('MAXY', $lgo->getImageHY());
          $this->_vars->_setVar('MINX', -$lgo->getImageHX());
          $this->_vars->_setVar('MINY', -$lgo->getImageHY());
          $this->_istruecolor=$lgo->isTrueColor()?1:0;
          $this->_vars->_setVar('ISTRUECOLOR', $this->_istruecolor);
          $this->_vars->_setVar('ISTRUECOLOUR', $this->_istruecolor);          
          $this->_vars->_setVar('BLACK',0);
          $this->_vars->_setVar('BLUE',1);
          $this->_vars->_setVar('GREEN',2);
          $this->_vars->_setVar('CYAN',3);
          $this->_vars->_setVar('RED',4);
          $this->_vars->_setVar('MAGENTA',5);
          $this->_vars->_setVar('BROWN',6);
          $this->_vars->_setVar('LIGHTGRAY',7);
          $this->_vars->_setVar('DARKGRAY',8);
          $this->_vars->_setVar('LIGHTGREY',7);
          $this->_vars->_setVar('DARKGREY',8);
          $this->_vars->_setVar('LIGHTBLUE',9);
          $this->_vars->_setVar('LIGHTGREEN',10);
          $this->_vars->_setVar('LIGHTCYAN',11);
          $this->_vars->_setVar('LIGHTRED',12);
          $this->_vars->_setVar('LIGHTMAGENTA',13);
          $this->_vars->_setVar('YELLOW',14);
          $this->_vars->_setVar('WHITE',15);          
          $this->_vars->_setVar('POSX',0);
          $this->_vars->_setVar('POSY',0);
          $this->_vars->_setVar('DEGREE',0);
      }
      
      function setMaxTimeout($d)
      {
          $d=(integer)$d;
          if ($d<1) $d=1;
          if ($d>5) $d=5;
          $this->_maxT=$d;
      }
      
      function getMaxTimeout()
      {
          return ($this->_maxT);
      }
      
      function getMsg($code, $x=0, $y=0, $w='')
      {
          $code=(integer)$code;
          $m='';
          switch ($code)
          {
              case LOGO_OK:
              case LOGO_OK_PROC_RETURN: $m='OK - EXECUTED'; break;
              case LOGO_ERROR_UNFINISHED_COMMENTS: $m='ERROR - UNFINISHED COMMENTS'; break;
              case LOGO_ERROR_MISSING_COMMAND: $m='ERROR - MISSING COMMAND'; break;
              case LOGO_WARNING_NUMBER_ROUNDED: $m='WARNING - FLOAT ROUNDED AS INTEGER'; break;
              case LOGO_ERROR_MISSING_ARG: $m='ERROR - MISSING ARGUMENTS'; break;
              case LOGO_ERROR_BAD_COMMAND: $m='ERROR - UNKNOWN COMMAND OR PROCEDURE'; break;
              case LOGO_WARNING_UNSUPPORTED_BG_CHANGE: $m='WARNING - UNABLE TO CHANGE SCREEN COLOR IN PROCESS'; break;
              case LOGO_ERROR_TOO_MANY_LEFT: $m='ERROR - MISSING ]'; break;
              case LOGO_ERROR_TOO_MANY_RIGHT: $m='ERROR - MISSING ['; break;
              case LOGO_INFORMATION_TOO_MANY_WARNING: $m='MSG - TOO MANY WARNINGS, THE REST IGNORED'; break;
              case LOGO_ERROR_TIME_OUT: $m='ERROR - TIME OUT'; break;
              case LOGO_WARNING_MISSING_REPEAT_BODY: $m='WARNING - MISSING A GROUP STATMENT'; break;
              case LOGO_WARNING_NOT_FULLY_IMPLEMENTED: $m='WARNING - NOT FULLY IMPLEMENTED'; break;
              case LOGO_ERROR_STOP_NOT_IN_PROC: $m='ERROR - CAN ONLY USE STOP IN PROCEDURE'; break;
              case LOGO_ERROR_END_NOT_FOUND: $m='ERROR - NEED A END TO FINISH DEFINITION OF TO';break;
              case LOGO_ERROR_KEYWORD_IN_USE: $m='ERROR - PROCEDURE NAME IS A RESERVED KEYWORD'; break;
              case LOGO_ERROR_NESTED_PROCEDURE_NOT_ALLOWED: $m='ERROR - NESTED PROCEDURE NOT ALLOWED'; break;
              case LOGO_ERROR_INVALID_PROC_NAME: $m='ERROR - INVALID PROCEDURE NAME'; break;
              case LOGO_ERROR_PROC_DEFINED: $m='ERROR - PROCEDURE CAN NOT BE RE-DEFINED'; break;
              case LOGO_ERROR_NO_TO: $m='ERROR - CANNOT FIND TO TO START DEFINING PROCEDURE'; break;
              case LOGO_ERROR_INVALID_SYMBOL: $m='ERROR - NOT A VALID PROCEDURE NAME'; break;
              case LOGO_ERROR_TOO_MANY_PROC: $m='ERROR - EXCEED MAXIMUM '.$this->_maxProc.' DEFINED PROCEDURES '; break;
              case LOGO_WARNING_TURTLE_OUT: $m='WARNING - TURTLE IS OUT OF BOUND'; break;
              case LOGO_ERROR_REPEAT_PROC_ARG: $m='ERROR - DUPLICATION OF PROCEDURE ARGUMENTS'; break;
              case LOGO_ERROR_TOO_MANY_LEVELS: $m='ERROR - TOO MANY LEVELS OF PROCEDURE'; break;
              case LOGO_WARNING_LOCAL_MAKE_GLOBALUSE: $m='WARNING - LOCALMAKE GLOBALLY USE (NOT DELETED)'; break;
              case LOGO_ERROR_MAKE_NEED_QUOTE: $m='ERROR - MAKE VARIABLE NEEDS DOUBLE QUOTA'; break;
              case LOGO_ERROR_MAKE_INVALID_NAME: $m='ERROR - MAKE VARIABLE IS NOT A VALID KEYWORD'; break;
              case LOGO_ERROR_MAKE_INVALID_VALUE: $m='ERROR - MAKE DOES NOT HAVE A VALID VALUE'; break;
              case LOGO_ERROR_UNKNOWN_GROUP: $m='ERROR - UNKNOWN ACTION TO START A GROUP ['; break;
              case LOGO_ERROR_NO_REPEAT_TIME: $m='ERROR - NO ENOUGH INPUT TO REPEAT'; break;
              case LOGO_ERROR_UNSUPPORTED_GROUP_ACTION: $m='ERROR - UNSUPPORTED GROUP ACTION'; break;
              case LOGO_ERROR_MISSING_BOOLEAN: $m='ERROR - IF STATEMENT MISSING BOOLEAN EXPRESSION'; break;
              case LOGO_WARNING_UNSUPPORTED_COLOR: $m='WARNING - UNSUPPORTED COLOR'; break;
              default: $m='ERROR - UNKNOWN REASONS FAILED THE PROCESS';break;
          }
          $s='';
          $extra='';
          if (strlen($w)>8) $w=substr($w,0,8).'[..]';
          if ($x&&$y)
          {
              if ($w)
              {
                  $extra=' - ('.$w.')';
              }
              $s=$m."$extra AT ROW ".$y.' COL '.$x;
          }
          else
          {
              if ($this->_lineW)
              {
                  $extra=' - ( '.$this->_lineW.' )';
              }
              $s=$m."$extra AT ROW ".$this->_lineY.' COL '.$this->_lineX;
          }
          if (($this->_src_line)&&($code!=LOGO_OK))
          {
              $extra=' (__LINE__:'.$this->_src_line.')';
          }
          return ($s.$extra);
      }
      
      function getMemAndTime()
      {
          return ('[IN '.$this->_endT.' SECONDS, '.(memory_get_usage()).' BYTES ALLOCATED]');
      }
      
      public static function isSymbol($s)
      {
          $__tmp = strlen($s);
          if ($__tmp==0) return (false);
          $ch=$s[0];
          if (isDigit($ch)) return (false);
          for ($i=0;$i<$__tmp;$i++)
          {
              $ch=$s[$i];
              if (!((isChar($ch))||(isDigit($ch))||($ch=='_')))
              {
                  return (false);
              }
          }
          return (true);
      }
      
      function isGood($s)
      {
          return ( (LogoParser::isSymbol($s)) && (!in_array($s, $this->_keywords))
          &&(!in_array($s, $this->_keywords_args))
          &&(!in_array($s, $this->_to_names))
          );
      }
      
      public static function str2num($str, &$changes)
      {
          $t=strlen($str);
          $changes=true;
          $str = preg_replace('`([^+\-*=/\(\)0-9<>&|\.%]*)`','',$str);
          if (strlen($str)==0)
          {
              $str = '0';
          }
          else
          {
              if ($t==strlen($str))
              {
                  eval("\$str = $str;");
                  $changes=false;
              }
              else
              {
                  $str = '0';
              }
          }
          return ($str);
      }
      
      function isNumber($s, &$realnum, &$value)
      {
          if (strpos($s, '==')===false)
          {
              $s=str_replace('=','==',$s);
          }
          foreach ($this->_makevars->keys() as $keys)
          {
              $s=str_replace(':'.$keys, $this->_makevars->getVar($keys), $s);
          }
          foreach ($this->_vars->keys() as $keys)
          {
              $s=str_replace(':'.$keys, $this->_vars->getVar($keys), $s);
          }
          $s=str_replace($this->_vars->keys(), $this->_vars->values(), $s);
          if (count($this->_runningProc) > 0)
          {
              $procVarIdx=array_search($this->_runningProc[count($this->_runningProc)-1], $this->_to_names);
              if ($procVarIdx!==false)
              {
                foreach ($this->_to_args[$procVarIdx]->keys() as $key)
                {
                    $s=str_replace(':'.$key, $this->_to_args[$procVarIdx]->getVar($key), $s);
                }
              }
          }
          $s=str_replace('RANDOMNUMBER0_100',mt_rand(0,100), $s);
          $value=LogoParser::str2num($s, $c);
          $realnum=false;
          if (!$c)
          {
              $realnum=is_float($value);
              //$value=$value;
              return (true);
          }
          $value=(integer)$value;
          return (false);
      }
      
      public static function getNextWord($s, $i, $U, &$j)
      {
          $_k=$i;
          while (($i<=$U)&&(isSpace($s[$i]))) 
          { 
            $i++; 
          }
          if ($i>$U)
          {
              $j=$U;
              return (trim(substr($s, $_k)));
          }
          $ch = $s[$i];          
          if (($ch=='[') || ($ch==']') || ($ch==';') || ($ch=='#'))
          {
              $j=$i;
              return ($ch);
          }
          $_k = $i;
          while ( ( ($i<=$U) ) && 
            ($s[$i]!='[') && ($s[$i]!=']') &&
            ($s[$i]!=';') && ($s[$i]!='#')
          )
          {
              if ($i+1<=$U)
              {
                if ($s[$i]=='/')
                {
                  $ch=$s[$i+1];
                  if (($ch=='/')||($ch=='*'))
                  {
                    break;
                  }
                }
              }
              if (isSpace($s[$i]))
              {
                break;      
              }                                            
              $i++;
          }
          $j=$i-1;
          return trim((substr($s,$_k, $i-$_k)));
      }
            
      function printWarnings()
      {
          $i=0;
          $j=-$this->_logo->getImageHY();
          $t=1;
          $maxcount = count($this->_warnings);
          while ($i<$maxcount)
          {
              $j+=$this->_logo->printText(-$this->_logo->getImageHX(), $j,
              $this->getMsg($this->_warnings[$i],
              $this->_warnings[$i+1],
              $this->_warnings[$i+2],
              $this->_warnings[$i+3])
              );
              $t++;
              if ($t>$this->_maxW)
              {
                  $j+=$this->_logo->printText(-$this->_logo->getImageHX(), $j,
                  $this->getMsg(LOGO_INFORMATION_TOO_MANY_WARNING)
                  );
                  break;
              }
              $i+=4;
          }
          return ($this->_logo->getIYd($j));
      }
      
      function pushWarn($code, $x, $y, $w)
      {
          $t=(integer)(((count($this->_warnings)+1)/4)-1);
          if ($t>$this->_maxW)
          {
              return;
          }
          $same=false;
          $maxcount = count($this->_warnings);
          for ($i=0;$i<$maxcount;$i+=4)
          {
              if (  ($code==$this->_warnings[$i]) &&
              ($x==$this->_warnings[$i+1]) &&
              ($y==$this->_warnings[$i+2])
              )
              {
                  $same=true;
                  break;
              }
          }
          if (!$same)
          {            
              array_push($this->_warnings, $code, $x, $y, $w);
          }
      }
      
      function getX()
      {
          return ($this->_lineX);
      }
      
      function getY()
      {
          return ($this->_lineY);
      }
      
      function getW()
      {
          return ($this->_lineW);
      }
      
      function _getXY($s, $d, $w='')
      {
          $i=0;
          $x=0;
          $j=1;
          while ($i<$d)
          {
              $x++;
              if (($s[$i]=="\n"))
              {
                  $j++;
                  $x=0;
              }
              $i++;
          }
          $this->_lineX=$x+1;
          $this->_lineY=$j;
          $this->_lineW=$w;
      }
      
      function removeLocalVars()
      {
          $__tmp = count($this->_runningProc);
          if ($__tmp == 0) return;
          $k=array_search($this->_runningProc[$__tmp-1], $this->_to_names);
          if ($k===false) return;
          //$s=$this->_localmake;
          foreach ($this->_localmake as $key=>$v)
          {
              if ($v[0]==$this->_to_names[$k])
              {
                  $this->_to_args[$k]->delVar($v[1]);
                  unset($this->_localmake[$key]);
              }
          }
      }
      
      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) 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')
                      {
                          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;
                          for ($tt=0;$tt<$lastRT;$tt++)
                          {
                              $t=$this->_parse($s, $groupstart+1, $i-1);
                              if ($t!=LOGO_OK) 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);
                          }
                      }  
                      $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;
                  }
              } // Not _inProc
              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'))
                  {
                      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=='WINDOW')
                      {
                          $this->_logo->setWrap(LOGO_WINDOW);
                      }
                      else
                      if ($w=='FENCE')
                      {
                          $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'))
                  {
                      if (count($this->_coms)>0)
                      {
                          $this->_getXY($s, $i, $w);
                          $this->_src_line=__LINE__;
                          return (LOGO_ERROR_MISSING_ARG);
                      }
                      $this->_logo->cs();
                      $this->_getXY($s, $i, $w);
                      $this->_src_line=__LINE__;
                      $this->pushWarn( LOGO_WARNING_NOT_FULLY_IMPLEMENTED,
                      $this->_lineX,
                      $this->_lineY,
                      $w
                      );
                      $i=$j;
                      $this->_vars->_setVar('POSX', $this->_logo->getX());
                      $this->_vars->_setVar('POSY', $this->_logo->getY());
                      $this->_vars->_setVar('DEGREE', $this->_logo->getD());
                      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()*pi()/180));
                          $y2=round($y1-$value*cos($this->_logo->getD()*pi()/180));
                          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=(integer)$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=(integer)$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'))
                  {
                      //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'))
                  {
                      // 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=='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);
      }
      
      function parse($s='')
      {
          $this->_runningT = microtime();
          $t = false;
          $len = strlen($s);
          if ($len > 0)
          {
              $t = $this->_parse($s, 0, $len - 1);
          }
          $this->_logo->drawTurtle();
          return ($t);
      }    
  }	
?>