File dsl/executor/DslInterpreter.class.php
Last commit: Tue Jul 19 00:10:39 2022 +0200 Jan Dankert Fetched from upstream.
1 <?php 2 3 namespace dsl\executor; 4 5 use dsl\DslAstParser; 6 use dsl\DslException; 7 use dsl\DslLexer; 8 use dsl\standard\ArrayWrapper; 9 use dsl\standard\NumberInstance; 10 use dsl\standard\NumberWrapper; 11 use dsl\standard\Script; 12 use dsl\standard\ArrayInstance; 13 use dsl\standard\DateWrapper; 14 use dsl\standard\MathWrapper; 15 use dsl\standard\StringInstance; 16 use dsl\standard\StringWrapper; 17 use dsl\standard\System; 18 use dsl\standard\Writer; 19 use dsl\standard\WriteWrapper; 20 21 class DslInterpreter 22 { 23 /** 24 * Execution context. 25 * 26 * @var array 27 */ 28 private $context = []; 29 30 /** 31 * Holds a reference to the write()-Function for getting the output buffer after execution. 32 * @var Writer 33 */ 34 private $writer; 35 private $flags; 36 37 const FLAG_SHOW_ERROR = 1; 38 const FLAG_SHOW_TRACE = 2; 39 const FLAG_THROW_ERROR = 4; 40 const FLAG_DEBUG = 8; 41 const FLAG_SECURE = 16; 42 43 private static $secure = true; 44 45 public function __construct( $flags = self::FLAG_SHOW_ERROR + self::FLAG_SECURE ) 46 { 47 $this->flags = $flags; 48 49 self::$secure = boolval($this->flags & self::FLAG_SECURE ); 50 51 // Standard-Globals 52 $this->addContext( [ 53 54 // Standard JS objects 55 'Math' => new MathWrapper(), 56 'Array' => new ArrayWrapper(), 57 'String' => new StringWrapper(), 58 'Number' => new NumberWrapper(), 59 'Date' => new DateWrapper(), 60 61 // Custom Scriptbox objects 62 'System' => new System(), 63 'write' => $this->writer = new Writer(), 64 'writeln' => new WriteWrapper( $this->writer,"\n" ), 65 'print' => new WriteWrapper( $this->writer,'' ), 66 'println' => new WriteWrapper( $this->writer,"\n" ), 67 ] ); 68 } 69 70 /** 71 * adds an external context to the interpreter environment. 72 * 73 * @param $context [] 74 */ 75 public function addContext($context ) { 76 $this->context = array_merge( $this->context, $context ); 77 } 78 79 80 /** 81 * Parses and runs the DSL code. 82 * 83 * @param $code String Script-Code 84 * @throws DslException 85 * @return mixed value of last return statement (if any) 86 */ 87 public function runCode( $code ) { 88 89 // Step 1: Splitting the source code into tokens (the "Lexer") 90 $lexer = new DslLexer(); 91 $token = $lexer->tokenize( $code ); 92 93 // Step 2: Creating a syntax tree (abstract syntax tree, AST). 94 try { 95 96 $parser = new DslAstParser(); 97 $parser->parse( $token ); 98 99 //if ( $this->flags & self::FLAG_DEBUG ) 100 // it has no security impact, so lets do it always. 101 $this->addContext( 102 [ 'Script' => new Script( $token,$parser->rootStatement ) ] 103 ); 104 105 // Step 3: Executing the syntax tree. 106 return $parser->execute( $this->context ); 107 } catch ( \Exception $e ) { 108 if ( $this->flags & self::FLAG_SHOW_ERROR ) { 109 if ( $this->flags & self::FLAG_SHOW_TRACE ) 110 $this->writer->buffer .= $e->__toString(); 111 else 112 $this->writer->buffer .= $e->getMessage(); 113 } 114 if ( $this->flags & self::FLAG_THROW_ERROR ) 115 throw $e; 116 } 117 } 118 119 120 /** 121 * Gets the output which was written by the code. 122 * 123 * @return mixed 124 */ 125 public function getOutput() { 126 127 return $this->writer->buffer; 128 } 129 130 /** 131 * @return bool 132 */ 133 public static function isSecure() { 134 return self::$secure; 135 } 136 }
Downloaddsl/executor/DslInterpreter.class.php
History Tue, 19 Jul 2022 00:10:39 +0200 Jan Dankert Fetched from upstream. Mon, 27 Jun 2022 00:41:50 +0200 Jan Dankert Fetched from upstream. Sun, 26 Jun 2022 15:47:05 +0200 Jan Dankert Fetched from upstream. Mon, 6 Jun 2022 14:06:46 +0200 Jan Dankert First commit after fetching from upstream repo.