2024-05-11 17:47:33 +03:00
< ? php
2024-05-11 18:42:44 +03:00
/*
* ************************************************************
| Компилятор LIS => BAS для MobileBASIC
| ( с ) Андрей Рейгант
| http :// vk . com / holdfast
| http :// mbteam . ru
* ************************************************************
| Пример :
-------------------------------------------------------------
* ** открыть исходный код MobileBASIC для компиляции в файл Autorun . bas
$lis = new LIS ( '10 SLEEP 5000' , 'Autorun.bas' );
| или $lis = new LIS ( file_get_contents ( 'code.lis' ), 'Autorun.bas' );
* ** компилировать файл
$lis -> compile ();
* ************************************************************
2024-05-11 17:47:33 +03:00
*/
class LIS {
2024-05-11 18:42:44 +03:00
public $data , $file , $save , $coderror , $warning , $bufbody , $buffer , $compile = false ;
public $lines = [];
public $ltypes = [];
2024-05-11 17:47:33 +03:00
public $lexems = [];
2024-05-11 18:42:44 +03:00
public $vars = [];
public $vtypes = [];
2024-05-11 17:47:33 +03:00
public $currLine ;
2024-05-11 18:42:44 +03:00
public $float = array ();
public $ver = 1 ; //Version (1 - 1.8.2, 2 - 1.9.1)
2024-05-11 17:47:33 +03:00
const INT = 0 , FLOAT = 1 , STR = 2 ;
const Operator = 0 , Integer = 1 , Float = 2 , String = 3 , Variable = 4 , Data = 5 , ArrayByte = 6 ;
2024-05-11 18:42:44 +03:00
public $ops = array ( " STOP " , " POP " , " RETURN " , " END " , " NEW " , " RUN " , " DIR " , " DEG " , " RAD " , " BYE " , " GOTO " , " GOSUB " , " SLEEP " , " PRINT " , " REM " , " DIM " , " IF " , " THEN " , " CLS " , " PLOT " , " DRAWLINE " , " FILLRECT " , " DRAWRECT " , " FILLROUNDRECT " , " DRAWROUNDRECT " , " FILLARC " , " DRAWARC " , " DRAWSTRING " , " SETCOLOR " , " BLIT " , " FOR " , " TO " , " STEP " , " NEXT " , " INPUT " , " LIST " , " ENTER " , " LOAD " , " SAVE " , " DELETE " , " EDIT " , " TRAP " , " OPEN " , " CLOSE " , " NOTE " , " POINT " , " PUT " , " GET " , " DATA " , " RESTORE " , " READ " , " = " , " <> " , " < " , " <= " , " > " , " >= " , " ( " , " ) " , " , " , " + " , " - " , " - " , " * " , " / " , " ^ " , " BITAND " , " BITOR " , " BITXOR " , " NOT " , " AND " , " OR " , " SCREENWIDTH " , " SCREENHEIGHT " , " ISCOLOR " , " NUMCOLORS " , " STRINGWIDTH " , " STRINGHEIGHT " , " LEFT $ " , " MID $ " , " RIGHT $ " , " CHR $ " , " STR $ " , " LEN " , " ASC " , " VAL " , " UP " , " DOWN " , " LEFT " , " RIGHT " , " FIRE " , " GAMEA " , " GAMEB " , " GAMEC " , " GAMED " , " DAYS " , " MILLISECONDS " , " YEAR " , " MONTH " , " DAY " , " HOUR " , " MINUTE " , " SECOND " , " MILLISECOND " , " RND " , " ERR " , " FRE " , " MOD " , " EDITFORM " , " GAUGEFORM " , " CHOICEFORM " , " DATEFORM " , " MESSAGEFORM " , " LOG " , " EXP " , " SQR " , " SIN " , " COS " , " TAN " , " ASIN " , " ACOS " , " ATAN " , " ABS " , " = " , " # " , " PRINT " , " INPUT " , " : " , " GELGRAB " , " DRAWGEL " , " SPRITEGEL " , " SPRITEMOVE " , " SPRITEHIT " , " READDIR $ " , " PROPERTY $ " , " GELLOAD " , " GELWIDTH " , " GELHEIGHT " , " PLAYWAV " , " PLAYTONE " , " INKEY " , " SELECT " , " ALERT " , " SETFONT " , " MENUADD " , " MENUITEM " , " MENUREMOVE " , " CALL " , " ENDSUB " , " REPAINT " , " SENDSMS " , " RAND " , " ALPHAGEL " , " COLORALPHAGEL " , " PLATFORMREQUEST " , " DELGEL " , " DELSPRITE " , " MKDIR " );
2024-05-11 17:47:33 +03:00
public $keywords = array ( " STOP " , " POP " , " RETURN " , " END " , " RUN " , " DIR " , " DEG " , " RAD " , " BYE " , " CLS " , " ENDSUB " );
2024-05-11 18:42:44 +03:00
public $functions = array ( " NEW " , " GOTO " , " GOSUB " , " SLEEP " , " PRINT " , " REM " , " DIM " , " IF " , " THEN " , " PLOT " , " DRAWLINE " , " FILLRECT " , " DRAWRECT " , " FILLROUNDRECT " , " DRAWROUNDRECT " , " FILLARC " , " DRAWARC " , " DRAWSTRING " , " SETCOLOR " , " BLIT " , " FOR " , " TO " , " STEP " , " NEXT " , " INPUT " , " LIST " , " ENTER " , " LOAD " , " SAVE " , " DELETE " , " EDIT " , " TRAP " , " OPEN " , " CLOSE " , " NOTE " , " POINT " , " PUT " , " GET " , " DATA " , " RESTORE " , " READ " , " BITAND " , " BITOR " , " BITXOR " , " NOT " , " AND " , " OR " , " SCREENWIDTH " , " SCREENHEIGHT " , " ISCOLOR " , " NUMCOLORS " , " STRINGWIDTH " , " STRINGHEIGHT " , " LEFT $ " , " MID $ " , " RIGHT $ " , " CHR $ " , " STR $ " , " LEN " , " ASC " , " VAL " , " UP " , " DOWN " , " LEFT " , " RIGHT " , " FIRE " , " GAMEA " , " GAMEB " , " GAMEC " , " GAMED " , " DAYS " , " MILLISECONDS " , " YEAR " , " MONTH " , " DAY " , " HOUR " , " MINUTE " , " SECOND " , " MILLISECOND " , " RND " , " ERR " , " FRE " , " MOD " , " EDITFORM " , " GAUGEFORM " , " CHOICEFORM " , " DATEFORM " , " MESSAGEFORM " , " LOG " , " EXP " , " SQR " , " SIN " , " COS " , " TAN " , " ASIN " , " ACOS " , " ATAN " , " ABS " , " = " , " # " , " PRINT " , " INPUT " , " : " , " GELGRAB " , " DRAWGEL " , " SPRITEGEL " , " SPRITEMOVE " , " SPRITEHIT " , " READDIR $ " , " PROPERTY $ " , " GELLOAD " , " GELWIDTH " , " GELHEIGHT " , " PLAYWAV " , " PLAYTONE " , " INKEY " , " SELECT " , " ALERT " , " SETFONT " , " MENUADD " , " MENUITEM " , " MENUREMOVE " , " CALL " , " SENDSMS " , " RAND " , " ALPHAGEL " , " COLORALPHAGEL " , " PLATFORMREQUEST " , " DELGEL " , " DELSPRITE " , " MKDIR " );
public $func191 = array ( " REPAINT " , " SENDSMS " , " RAND " , " ALPHAGEL " , " COLORALPHAGEL " , " PLATFORMREQUEST " , " DELGEL " , " DELSPRITE " , " MKDIR " );
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
function __construct ( $name , $newname , $v = 1 ) {
2024-05-11 17:47:33 +03:00
$this -> file = $name ;
$this -> save = $newname ;
2024-05-11 18:42:44 +03:00
if ( $v > 0 && $v < 3 )
$this -> ver = $v ;
2024-05-11 17:47:33 +03:00
}
function compile () {
if ( ! $this -> compile ) {
$string = explode ( " \n " , $this -> data );
for ( $i = 0 ; $i < count ( $string ); $i ++ ) {
if ( trim ( $string [ $i ]) != " " ) {
$this -> lines [] = trim ( $string [ $i ]);
}
}
$this -> analize ();
if ( $this -> coderror != " " )
2024-05-11 18:42:44 +03:00
return array ( " error " , $this -> coderror );
2024-05-11 17:47:33 +03:00
$this -> compileCode ();
file_put_contents ( $this -> save , $this -> buffer );
$this -> compile = true ;
2024-05-11 18:42:44 +03:00
if ( $this -> warning != " " )
return array ( " warning " , $this -> warning );
2024-05-11 17:47:33 +03:00
}
}
function analize () {
2024-05-11 18:42:44 +03:00
$this -> currLine = 0 ;
for ( $i = 0 ; $i < count ( $this -> lines ); $i ++ ) {
2024-05-11 17:47:33 +03:00
$this -> analizeLine ( $this -> lines [ $i ]);
$this -> check ( $this -> currLine );
$this -> currLine ++ ;
if ( $this -> coderror != " " )
break ;
}
}
function check ( $lineNum ) {
$bracketCount = 0 ;
if ( $this -> ltypes [ $lineNum ][ 0 ] != self :: Integer ) {
2024-05-11 18:42:44 +03:00
$this -> error ( " Invalid line number [ " . $this -> lexems [ $lineNum ][ 0 ] . " ] " );
2024-05-11 17:47:33 +03:00
}
2024-05-11 18:42:44 +03:00
if ( $this -> ltypes [ $lineNum ][ 1 ] == self :: Variable ) {
if ( ! in_array ( $this -> lexems [ $lineNum ][ 2 ], $this -> ops )) {
$this -> error ( " Error function [ " . $this -> lexems [ $lineNum ][ 1 ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);
}
}
if ( strlen ( $this -> lexems [ $lineNum ][ 1 ]) == 0 )
$this -> error ( " Error at line[ " . $this -> lexems [ $lineNum ][ 0 ] . " ] " );
2024-05-11 17:47:33 +03:00
for ( $i = 0 ; $i < count ( $this -> lexems [ $lineNum ]); $i ++ ) {
if ( $this -> lexems [ $lineNum ][ $i ] == " ( " )
$bracketCount ++ ;
if ( $this -> lexems [ $lineNum ][ $i ] == " ) " )
$bracketCount -- ;
}
for ( $ii = 0 ; $ii < count ( $this -> lexems [ $lineNum ]); $ii ++ ) {
$i = $ii ;
2024-05-11 18:42:44 +03:00
if ( $this -> lexems [ $lineNum ][ $ii ] == " > " && $this -> lexems [ $lineNum ][ $ii + 1 ] == " = " ) {
$this -> lexems [ $lineNum ][ $ii ] = '>=' ;
$this -> lexems [ $lineNum ][ $ii + 1 ] = '' ;
$this -> ltype [ $lineNum ][ $ii + 1 ] = '' ;
} elseif ( $this -> lexems [ $lineNum ][ $ii ] == " < " && $this -> lexems [ $lineNum ][ $ii + 1 ] == " = " ) {
$this -> lexems [ $lineNum ][ $ii ] = '<=' ;
$this -> lexems [ $lineNum ][ $ii + 1 ] = '' ;
$this -> ltype [ $lineNum ][ $ii + 1 ] = '' ;
} elseif ( $this -> lexems [ $lineNum ][ $ii ] == " < " && $this -> lexems [ $lineNum ][ $ii + 1 ] == " > " ) {
$this -> lexems [ $lineNum ][ $ii ] = '<>' ;
$this -> lexems [ $lineNum ][ $ii + 1 ] = '' ;
$this -> ltype [ $lineNum ][ $ii + 1 ] = '' ;
}
if ( $this -> ltypes [ $lineNum ][ $i ] == Variable ) {
if ( $this -> lexems [ $lineNum ][ $i - 1 ] == '$' || $this -> lexems [ $lineNum ][ $i - 1 ] == '%' )
$this -> error ( " Uncorrect variable name [ " . $this -> lexems [ $lineNum ][ $i ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);;
}
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
if ( $this -> lexems [ $lineNum ][ $i ] == " = " ) {
if ( mb_strlen ( $this -> lexems [ $lineNum ][ $i + 1 ]) < 1 )
$this -> error ( " Null after [ " . $this -> lexems [ $lineNum ][ $i ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);
}
2024-05-11 17:47:33 +03:00
if ( $this -> ltypes [ $lineNum ][ $i ] == self :: Operator ) {
2024-05-11 18:42:44 +03:00
if ( $this -> ver == 1 && in_array ( $this -> lexems [ $lineNum ][ $i ], $this -> func191 )) {
if ( $this -> lexems [ $lineNum ][ $i ] != " REPAINT " )
$this -> error ( " Operator [ " . $this -> lexems [ $lineNum ][ $i ] . " ] is not supported in MobileBASIC 1.8.6 on line " . $this -> lexems [ $lineNum ][ 0 ]); else {
$this -> warn ( " Operator [REPAINT] not support in MobileBASIC 1.8.6, this operator will removed from code. Select 1.9.1 version of basic to use operator REPAINT " );
if ( $this -> lexems [ $lineNum ][ $i - 1 ] == " : " ) {
$this -> lexems [ $lineNum ][ $i ] = " " ;
$this -> lexems [ $lineNum ][ $i - 1 ] = " " ;
} elseif ( $this -> lexems [ $lineNum ][ $i + 1 ] = " : " ) {
$this -> lexems [ $lineNum ][ $i ] = " " ;
$this -> lexems [ $lineNum ][ $i + 1 ] = " " ;
}
else
$this -> lexems [ $lineNum ] = " " ;
}
} elseif ( in_array ( $this -> lexems [ $lineNum ][ $i ], $this -> keywords )) {
2024-05-11 17:47:33 +03:00
if ( ! ( $i == count ( $this -> lexems [ $lineNum ]) - 1 || $this -> lexems [ $lineNum ][ $i + 1 ] == " : " ))
2024-05-11 18:42:44 +03:00
$this -> error ( " Operator must have 0 arguments [ " . $this -> lexems [ $lineNum ][ $i ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);
}
elseif ( in_array ( $this -> lexems [ $lineNum ][ $i ], $this -> functions )) {
if ( $i == count ( $this -> lexems [ $lineNum ]) - 1 || $this -> lexems [ $lineNum ][ $i + 1 ] == " : "
|| $this -> lexems [ $lineNum ][ $i + 1 ] != " ( " && $this -> lexems [ $lineNum ][ $i + 1 ] != " : "
&& mb_strlen ( $this -> lexems [ $lineNum ][ $i + 1 ]) < 1 )
$this -> error ( " Error function [ " . $this -> lexems [ $lineNum ][ $i ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);
}
elseif ( ! in_array ( $this -> lexems [ $lineNum ][ $i ], $this -> functions ) && mb_strlen ( $this -> lexems [ $lineNum ][ $i ]) > 1 ) {
2024-05-11 17:47:33 +03:00
if ( $i == count ( $this -> lexems [ $lineNum ]) - 1 || $this -> lexems [ $lineNum ][ $i + 1 ] == " : " ) {
2024-05-11 18:42:44 +03:00
$this -> error ( " Operator must have arguments [ " . $this -> lexems [ $lineNum ][ $i ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);
2024-05-11 17:47:33 +03:00
} elseif ( $this -> lexems [ $lineNum ][ $i + 1 ] == " ( " && $this -> lexems [ $lineNum ][ $i ] != " TO " && $this -> lexems [ $lineNum ][ $i ] != " STEP " ) {
2024-05-11 18:42:44 +03:00
$this -> error ( " Not an operator [ " . $this -> lexems [ $lineNum ][ $i ] . " ] on line " . $this -> lexems [ $lineNum ][ 0 ]);
2024-05-11 17:47:33 +03:00
}
}
if ( $this -> lexems [ $lineNum ][ $i ] == " DIM " ) {
2024-05-11 18:42:44 +03:00
array_splice ( $this -> lexems [ $lineNum ], $i + 2 , 0 , " " );
array_splice ( $this -> ltypes [ $lineNum ], $i + 2 , 0 , self :: ArrayByte );
2024-05-11 17:47:33 +03:00
}
2024-05-11 18:42:44 +03:00
} elseif ( $this -> ltypes [ $lineNum ][ $i ] == self :: Variable && $this -> lexems [ $lineNum ][ $i + 1 ] == " ( " ) {
array_splice ( $this -> lexems [ $lineNum ], $i + 1 , 0 , " " );
array_splice ( $this -> ltypes [ $lineNum ], $i + 1 , 0 , self :: ArrayByte );
2024-05-11 17:47:33 +03:00
}
}
if ( $bracketCount != 0 ) {
2024-05-11 18:42:44 +03:00
$this -> error ( " Error: Some bracket not opened/closed on line " . $this -> lexems [ $lineNum ][ 0 ]);
2024-05-11 17:47:33 +03:00
return ;
}
}
function analizeLine ( $line ) {
$i = 0 ;
while ( $i < mb_strlen ( $line )) {
$i += $this -> readToken ( $line , $i );
if ( $this -> coderror != " " )
break ;
}
}
function isLetter ( $ch ) {
return ( $ch >= 'A' && $ch <= 'Z' )
|| ( $ch >= 'a' && $ch <= 'z' );
}
function isDigit ( $ch ) {
return ( $ch >= '0' && $ch <= '9' );
}
function isLetterOrDigit ( $ch ) {
return $this -> isLetter ( $ch ) || $this -> isDigit ( $ch );
}
function isVariablePartSymbol ( $ch ) {
return ( $ch == '_' || $ch == '$' || $ch == '%' );
}
function isValidVariableChar ( $ch ) {
return $this -> isLetterOrDigit ( $ch ) || $this -> isVariablePartSymbol ( $ch );
}
function readToken ( $line , $startPos ) {
$initPos = $startPos ;
$op = " " ;
if ( $this -> isLetter ( mb_substr ( $line , $startPos , 1 ))) {
while ( $this -> isValidVariableChar ( mb_substr ( $line , $startPos , 1 ))) {
$op .= mb_substr ( $line , $startPos , 1 );
$startPos ++ ;
if ( $startPos >= mb_strlen ( $line ))
break ;
}
$op = mb_strtoupper ( $op );
$this -> lexems [ $this -> currLine ][] = $op ;
// echo "лан, не урчи";
$isData = false ;
$data = " " ;
if ( $op == " DATA " || $op == " REM " ) {
$isData = true ;
$startPos ++ ;
while ( $startPos < mb_strlen ( $line )) {
$data .= mb_substr ( $line , $startPos , 1 );
$startPos ++ ;
}
$this -> lexems [ $this -> currLine ][] = $data ;
}
if ( ! in_array ( $op , $this -> ops )) {
if ( ! in_array ( $op , $this -> vars ))
$this -> vars [] = $op ;
$this -> ltypes [ $this -> currLine ][] = self :: Variable ;
} else {
$this -> ltypes [ $this -> currLine ][] = self :: Operator ;
if ( $isData ) {
$this -> ltypes [ $this -> currLine ][] = self :: Data ;
}
}
}
//STRING
elseif ( mb_substr ( $line , $startPos , 1 ) == '"' ) {
$startPos ++ ;
2024-05-11 18:42:44 +03:00
while ( ! ( mb_substr ( $line , $startPos , 1 ) == '"' ) || ( mb_substr ( $line , $startPos - 1 , 1 ) == '\\' )) {
if (( mb_substr ( $line , $startPos , 1 )) != '\\' )
$op .= mb_substr ( $line , $startPos , 1 );
2024-05-11 17:47:33 +03:00
$startPos ++ ;
if ( $startPos >= mb_strlen ( $line )) {
2024-05-11 18:42:44 +03:00
$this -> coderror = " Error complie: Not found close \" on line " . $this -> lexems [ $this -> currLine ][ 0 ];
2024-05-11 17:47:33 +03:00
break ;
}
}
$startPos ++ ;
$this -> lexems [ $this -> currLine ][] = '"' . $op . '"' ;
$this -> ltypes [ $this -> currLine ][] = self :: String ;
}
// NUMBER
elseif ( $this -> isDigit ( mb_substr ( $line , $startPos , 1 ))) {
while ( $this -> isDigit ( mb_substr ( $line , $startPos , 1 ))
|| mb_substr ( $line , $startPos , 1 ) == '.'
|| mb_substr ( $line , $startPos , 1 ) == 'e' || mb_substr ( $line , $startPos , 1 ) == 'E' ) {
$op .= mb_substr ( $line , $startPos , 1 );
if ( mb_substr ( $line , $startPos , 1 ) == 'e' || mb_substr ( $line , $startPos , 1 ) == 'E' ) {
$op .= mb_substr ( $line , $startPos + 1 , 1 );
$startPos += 2 ;
} else
$startPos ++ ;
if ( $startPos >= mb_strlen ( $line ))
break ;
}
$containPoint = false ;
$error = false ;
for ( $i = 0 ; $i < mb_strlen ( $op ); $i ++ ) {
if ( $op [ $i ] == '.' ) {
if ( ! $containPoint )
$containPoint = true ;
else {
// exit;
$this -> coderror = " NumberLexem contains more than one point [ " . $op . " ] " ;
return ;
}
}
}
if ( ! $error ) {
$this -> lexems [ $this -> currLine ][] = $op ;
2024-05-11 18:42:44 +03:00
if ( $containPoint ) {
2024-05-11 17:47:33 +03:00
$this -> ltypes [ $this -> currLine ][] = self :: Float ;
2024-05-11 18:42:44 +03:00
if ( ! in_array ( $op , $this -> float )) {
$this -> float [] = $op ;
}
} else
2024-05-11 17:47:33 +03:00
$this -> ltypes [ $this -> currLine ][] = self :: Integer ;
}
}
///SYMBOL
else {
if ( mb_substr ( $line , $startPos , 1 ) != ' ' && mb_substr ( $line , $startPos , 1 ) < 'А ' ) {
$this -> lexems [ $this -> currLine ][] = mb_substr ( $line , $startPos , 1 );
$this -> ltypes [ $this -> currLine ][] = self :: Operator ;
$startPos ++ ;
} elseif ( mb_substr ( $line , $startPos , 1 ) >= 'А ' && mb_substr ( $line , $startPos , 1 ) <= 'я' ) {
$this -> coderror = " SymbolLexem not recognized [ " . $line [ $startPos ] . " ] " ;
return ;
} else
$startPos ++ ;
}
return $startPos - $initPos ;
}
function compileHead () {
$buf = " " ;
2024-05-11 18:42:44 +03:00
if ( $this -> ver == 1 )
$buf .= pack ( 'H*' , " 4d420001 " );
else
$buf .= pack ( 'H*' , " 4d420191 " );
$buf .= pack ( 'n*' , count ( $this -> vars ));
for ( $i = 0 ; $i < count ( $this -> vars ); $i ++ ) {
2024-05-11 17:47:33 +03:00
$buf .= $this -> writeUTF ( $this -> vars [ $i ]);
2024-05-11 18:42:44 +03:00
$type = substr ( $this -> vars [ $i ], - 1 );
switch ( $type ) {
case '$' :
$buf .= pack ( 'H*' , " 02 " );
2024-05-11 17:47:33 +03:00
break ;
2024-05-11 18:42:44 +03:00
default :
2024-05-11 17:47:33 +03:00
$buf .= pack ( 'H*' , " 01 " );
break ;
2024-05-11 18:42:44 +03:00
case '%' :
$buf .= pack ( 'H*' , " 00 " );
2024-05-11 17:47:33 +03:00
break ;
}
}
$buf .= pack ( 'n*' , strlen ( $this -> bufbody ));
$this -> buffer = $buf . $this -> bufbody ;
}
function compileCode () {
$lexems = $this -> lexems ;
$ltypes = $this -> ltypes ;
$buf = " " ;
2024-05-11 18:42:44 +03:00
for ( $currLine = 0 ; $currLine < count ( $lexems ); $currLine ++ ) {
2024-05-11 17:47:33 +03:00
$line = " " ;
2024-05-11 18:42:44 +03:00
$notnull = false ;
2024-05-11 17:47:33 +03:00
for ( $currLex = 1 ; $currLex < count ( $lexems [ $currLine ]); $currLex ++ ) {
2024-05-11 18:42:44 +03:00
if ( $lexems [ $currLine ][ $currLex ] != " " ) {
$notnull = true ;
break ;
}
}
if ( $notnull ) {
$buf .= pack ( 'n*' , $lexems [ $currLine ][ 0 ]);
for ( $currLex = 1 ; $currLex < count ( $lexems [ $currLine ]); $currLex ++ ) {
/////Operator
$ifStarted = false ;
$forStarted = false ;
if ( $ltypes [ $currLine ][ $currLex ] == self :: Operator ) {
if ( trim ( $lexems [ $currLine ][ $currLex ]) == " IF " ) {
$ifStarted = true ;
} elseif ( trim ( $lexems [ $currLine ][ $currLex ]) == " THEN " ) {
$ifStarted = false ;
} elseif ( trim ( $lexems [ $currLine ][ $currLex ]) == " FOR " ) {
$forStarted = true ;
}
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
for ( $i = 0 ; $i < count ( $this -> ops ); $i ++ ) {
if ( trim ( $lexems [ $currLine ][ $currLex ]) == $this -> ops [ $i ]) {
if ( trim ( $lexems [ $currLine ][ $currLex ]) == " = " ) {
if ( $ifStarted ) {
$i = " 33 " ;
} else if ( $forStarted ) {
$i = " 7b " ;
$forStarted = false ;
} else {
$i = " f6 " ;
}
2024-05-11 17:47:33 +03:00
} else {
2024-05-11 18:42:44 +03:00
$i = dechex ( $i );
if ( strlen ( $i ) < 2 )
$i = " 0 " . $i ;
2024-05-11 17:47:33 +03:00
}
2024-05-11 18:42:44 +03:00
if ( mb_strtoupper ( $i ) == " 3D " ) {
if ( $ltypes [ $currLine ][ $currLex - 1 ] != Integer && $ltypes [ $currLine ][ $currLex - 1 ] != Float && $ltypes [ $currLine ][ $currLex - 1 ] != Variable && $lexems [ $currLine ][ $currLex - 1 ] != " ) " )
$i = " 3e " ;
}
$line .= pack ( 'H*' , $i );
break ;
}
}
}
/////Variable
if ( $ltypes [ $currLine ][ $currLex ] == self :: Variable ) {
for ( $i = 0 ; $i < count ( $this -> vars ); $i ++ ) {
if ( trim ( $lexems [ $currLine ][ $currLex ]) == trim ( $this -> vars [ $i ])) {
$line .= pack ( 'H*' , " FC " );
2024-05-11 17:47:33 +03:00
$i = dechex ( $i );
2024-05-11 18:42:44 +03:00
//echo $i;
2024-05-11 17:47:33 +03:00
if ( strlen ( $i ) < 2 )
$i = " 0 " . $i ;
2024-05-11 18:42:44 +03:00
$line .= pack ( 'H*' , $i );
break ;
2024-05-11 17:47:33 +03:00
}
}
}
2024-05-11 18:42:44 +03:00
if ( $ltypes [ $currLine ][ $currLex ] == self :: ArrayByte ) {
$line .= pack ( 'H*' , " F7 " );
}
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
if ( $ltypes [ $currLine ][ $currLex ] == self :: Integer ) {
if ( strlen ( $lexems [ $currLine ][ $currLex ]) > 5 )
$ltypes [ $currLine ][ $currLex ] = self :: Float ;
else {
$val = intval ( $lexems [ $currLine ][ $currLex ]);
if ( $val <= 127 ) {
$line .= pack ( 'H*' , " F8 " );
$i = dechex ( $val );
if ( strlen ( $i ) < 2 )
$i = " 0 " . $i ;
$line .= pack ( 'H*' , $i );
} elseif ( $val >= 128 && $val <= 255 ) {
$line .= pack ( 'H*' , " F9 " );
$i = dechex ( $val );
if ( strlen ( $i ) < 2 )
$i = " 0 " . $i ;
$line .= pack ( 'H*' , $i );
} elseif ( $val >= 256 && $val < 65536 ) {
$line .= pack ( 'H*' , " FA " );
$line .= pack ( 'n*' , $val );
} else {
$line .= pack ( 'H*' , " FB " );
$line .= pack ( 'c' , $this -> shiftRight ( $val , 24 ) & 0xFF );
$line .= pack ( 'c' , $this -> shiftRight ( $val , 16 ) & 0xFF );
$line .= pack ( 'c' , $this -> shiftRight ( $val , 8 ) & 0xFF );
$line .= pack ( 'c' , $this -> shiftRight ( $val , 0 ) & 0xFF );
}
2024-05-11 17:47:33 +03:00
}
}
2024-05-11 18:42:44 +03:00
/////
if ( $ltypes [ $currLine ][ $currLex ] == self :: String ) {
$text = mb_substr ( $lexems [ $currLine ][ $currLex ], 1 , mb_strlen ( $lexems [ $currLine ][ $currLex ]) - 2 );
if ( preg_match ( '//u' , $text ))
$text = iconv ( " UTF-8 " , " WINDOWS-1251 " , $text );
$line .= pack ( 'H*' , " FD " );
$line .= $this -> writeTEXT ( $text );
}
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
if ( $ltypes [ $currLine ][ $currLex ] == self :: Data ) {
$line .= $this -> writeTEXT ( $lexems [ $currLine ][ $currLex ]);
}
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
if ( $ltypes [ $currLine ][ $currLex ] == self :: Float ) {
if ( $this -> ver == 1 ) {
$line .= pack ( 'H*' , " FE " );
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
$exp = 0x80 ;
2024-05-11 17:47:33 +03:00
2024-05-11 18:42:44 +03:00
$num = doubleval ( $lexems [ $currLine ][ $currLex ]);
if ( $num < 1 ) {
while ( $num < 1 ) {
$num = $num * 10 ;
$exp -- ;
}
} else if ( $num >= 10 ) {
while ( $num >= 10 ) {
$num = $num / 10 ;
$exp ++ ;
}
}
$radix = ( $num * 500000 );
$line .= pack ( 'c' , $this -> shiftRight ( $radix , 16 ) & 0xFF );
$line .= pack ( 'c' , $this -> shiftRight ( $radix , 8 ) & 0xFF );
$line .= pack ( 'c' , $this -> shiftRight ( $radix , 0 ) & 0xFF );
$line .= pack ( " c " , $exp );
} else {
///write float number
for ( $i = 0 ; $i < count ( $this -> float ); $i ++ ) {
if ( trim ( $lexems [ $currLine ][ $currLex ]) == trim ( $this -> float [ $i ])) {
//echo $lexems[$currLine][$currLex];
//echo trim($this->float[$i]);
$line .= pack ( 'H*' , " FE " );
$i = dechex ( $i );
//echo $i;
if ( strlen ( $i ) < 2 )
$i = " 0 " . $i ;
//echo $i.' ';
$line .= pack ( 'H*' , $i );
break ;
}
}
2024-05-11 17:47:33 +03:00
}
}
}
2024-05-11 18:42:44 +03:00
$len = dechex ( strlen ( $line ) + 4 );
if ( mb_strlen ( $len ) < 2 )
$len = " 0 " . $len ;
$buf .= pack ( 'H*' , $len ) . $line . pack ( 'H*' , 'FF' );
}
2024-05-11 17:47:33 +03:00
}
$this -> bufbody = $buf ;
$this -> compileHead ();
}
2024-05-11 18:42:44 +03:00
function error ( $text ) {
if ( empty ( $this -> coderror ))
$this -> coderror = $text ;
}
function warn ( $text ) {
if ( empty ( $this -> warning ))
$this -> warning = $text ;
}
2024-05-11 17:47:33 +03:00
function writeUTF ( $text ) {
$pack = pack ( 'n*' , mb_strlen ( $text ));
$pack .= pack ( 'a*' , $text );
return $pack ;
}
function writeTEXT ( $text ) {
$len = dechex ( strlen ( $text ));
if ( strlen ( $len ) < 2 )
$len = " 0 " . $len ;
$pack = pack ( 'H*' , $len );
$pack .= pack ( 'a*' , $text );
return $pack ;
}
function shiftRight ( $a , $b ) {
if ( is_numeric ( $a ) && $a < 0 ) {
return ( $a >> $b ) + ( 2 << ~ $b );
} else {
return ( $a >> $b );
}
}
function endWith ( $haystack , $needle ) {
$length = strlen ( $needle );
if ( $length == 0 ) {
return true ;
}
return ( substr ( $haystack , - $length ) === $needle );
}
}