Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- define( '_SPADDING', ' ' );
- function _spad( $data )
- {
- return str_replace( "\n", "\n" . _SPADDING, $data );
- }
- function _sdumpa( $data )
- {
- $out = "";
- foreach( $data as $k => $v )
- $out .= "\n" . _SPADDING . "$k=" . _spad( _sdump( $v ) );
- return $out;
- }
- function _sdump( $data )
- {
- if( is_object( $data ) )
- {
- $type = get_class( $data );
- return "($type)" . _sdumpa( (array) $data );
- }
- if( is_array( $data ) )
- return "(Array)" . _sdumpa( $data );
- else
- return $data;
- }
- function struct_dump( $data )
- {
- echo "<pre>";
- echo _sdump( $data );
- echo "</pre>";
- }
- function hdr( $h )
- {
- echo "<h3>$h</h3>";
- }
- $code =
- "
- set( 'x', add( 3, mul( 4, 5 ) ) );\n
- print( get( 'x' ) );
- ";
- hdr( "Code" );
- echo "<pre>$code</pre>";
- $tokens = array();
- function crtok( $type, $data )
- {
- return (object) array( "type" => $type, "data" => $data );
- }
- $codelen = strlen( $code );
- for( $i = 0; $i < $codelen; ++$i )
- {
- $fc = $code[ $i ];
- // whitespace
- if( strpos( " \n\r\t", $fc ) !== false )
- continue;
- // special symbol
- if( strpos( "(,);", $fc ) !== false )
- {
- $tokens[] = crtok( "spec", $fc );
- }
- // identifier
- if( ctype_alpha( $fc ) )
- {
- $name = '';
- while( $i < $codelen && ctype_alnum( $code[ $i ] ) )
- $name .= $code[ $i++ ];
- $tokens[] = crtok( "ident", $name );
- $i--;
- continue;
- }
- // number
- if( ctype_digit( $fc ) )
- {
- $num = "";
- while( $i < $codelen && ctype_digit( $code[ $i ] ) )
- $num .= $code[ $i++ ];
- $tokens[] = crtok( "number", $num );
- $i--;
- continue;
- }
- // string
- if( strpos( "\'\"", $fc ) !== false )
- {
- $i++;
- $string = "";
- $escaped = false;
- while( $i < $codelen )
- {
- if( $code[ $i ] == '\\' )
- $escaped = !$escaped;
- else
- $escaped = false;
- if( $code[ $i ] == $fc && !$escaped )
- break;
- $string .= $code[ $i++ ];
- }
- $tokens[] = crtok( "string", $string );
- }
- }
- function dumptokpart( $tokens, $b, $e )
- {
- for( ; $b < $e; ++$b )
- {
- echo $tokens[ $b ]->type;
- echo "(\"";
- echo $tokens[ $b ]->data;
- echo "\"); ";
- }
- echo "<br/>";
- }
- hdr( "Tokens" );
- dumptokpart( $tokens, 0, count( $tokens ) );
- hdr( 'Function tree generation' );
- $functree = array();
- function errif( $test, $out ){ if( $test ) echo "$out<br/>"; }
- function read_args( $tokens, $begin, $end )
- {
- echo "readargs: ";
- dumptokpart( $tokens, $begin, $end );
- $out = array();
- $i = $begin;
- $b = $i;
- $level = 0;
- while( $i <= $end )
- {
- if( ( $tokens[ $i ]->data == ',' || $tokens[ $i ]->data == ')' ) && $level == 0 )
- {
- $e = $i;
- // check all tokens from $b to $e
- if( $b < $e )
- {
- $ft = $tokens[ $b ];
- if( $ft->type == "string" )
- $out[] = $ft;
- else if( $ft->type == "number" )
- $out[] = $ft;
- else if( $ft->type == "ident" )
- {
- // a function!
- $out[] = make_func( $tokens, $b, $e );
- }
- else
- echo "unexpected token: $ft->type<br/>";
- }
- else
- echo "expected argument<br/>";
- $b = $i + 1;
- }
- if( $tokens[ $i ]->data == '(' ) $level++;
- else if( $tokens[ $i ]->data == ')' ) $level--;
- $i++;
- }
- return $out;
- }
- function make_func( $tokens, $b, $e )
- {
- echo "makefunc: ";
- dumptokpart( $tokens, $b, $e );
- errif( $tokens[ $b ]->type != 'ident', 'type of first not ident' );
- errif( $tokens[ $b + 1 ]->data != '(', 'data of second not (' );
- errif( $tokens[ $e - 1 ]->data != ')', 'data of last not )' );
- $name = $tokens[ $b ]->data;
- $args = read_args( $tokens, $b + 2, $e - 1 );
- return (object) array( "name" => $name, "args" => $args );
- }
- for( $i = 0; $i < count( $tokens ); ++$i )
- {
- $b = $i;
- while( $i < count( $tokens ) && $tokens[ $i ]->data != ';' )
- $i++;
- if( $i - $b <= 1 )
- continue;
- // process tokens from $beg to $i
- $functree[] = make_func( $tokens, $b, $i );
- }
- hdr( 'Function tree' );
- struct_dump( $functree );
- // the low-level code
- // flip the tree into a list of functions, assign registers and constants
- global $constants, $funclist, $oplist;
- $constants = array();
- $funclist = array();
- $oplist = array();
- function const_add( $data )
- {
- global $constants;
- if( ( $at = array_search( $data, $constants, true ) ) !== false )
- return $at;
- $constants[] = $data;
- return count( $constants ) - 1;
- }
- function fl_add( $func )
- {
- global $funclist;
- $args = array();
- foreach( $func->args as $arg )
- {
- if( isset( $arg->name ) )
- {
- // it's a function
- $reg = fl_add( $arg );
- $args[] = crtok( "reg", $reg );
- }
- else
- {
- // it's a constant
- $args[] = crtok( "const", const_add( $arg->data ) );
- }
- }
- $funclist[] = (object) array( "name" => $func->name, "args" => $args );
- return count( $funclist ) - 1;
- }
- foreach( $functree as $func )
- fl_add( $func );
- hdr( "Function list" );
- echo "FuncList: "; struct_dump( $funclist );
- echo "Constants: "; struct_dump( $constants );
- global $variables, $output;
- $variables = array();
- $output = "";
- function scrapi_add( $a1, $a2 ){ return $a1 + $a2; }
- function scrapi_sub( $a1, $a2 ){ return $a1 - $a2; }
- function scrapi_mul( $a1, $a2 ){ return $a1 * $a2; }
- function scrapi_div( $a1, $a2 ){ return $a1 / $a2; }
- function scrapi_set( $at, $val ){ global $variables; $variables[ $at ] = $val; }
- function scrapi_get( $at ){ global $variables; return $variables[ $at ]; }
- function scrapi_print( $what ){ global $output; $output .= $what; }
- $API = array(
- 'add' => 'scrapi_add',
- 'sub' => 'scrapi_sub',
- 'mul' => 'scrapi_mul',
- 'div' => 'scrapi_div',
- 'set' => 'scrapi_set',
- 'get' => 'scrapi_get',
- 'print' => 'scrapi_print'
- );
- hdr( "Execution" );
- $ptr = 0;
- foreach( $funclist as $op )
- {
- if( !isset( $API[ $op->name ] ) )
- echo "function not found: $op->name<br/>";
- else
- {
- $args = array();
- foreach( $op->args as $arg )
- {
- if( $arg->type == "const" )
- $args[] = $constants[ $arg->data ];
- else
- $args[] = $variables[ $arg->data ];
- }
- echo "$op->name( " . implode( ", ", $args ) . " );<br/>";
- $ret = call_user_func_array( $API[ $op->name ], $args );
- if( isset( $ret ) )
- $variables[ $ptr ] = $ret;
- }
- $ptr++;
- }
- hdr( "End of execution" );
- echo "Output: ";
- echo "<div style='border: 2px inset #ccc'>$output</div>";
- echo "Variables: "; struct_dump( $variables );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement