File modules/dsl/executor/DslInterpreter.class.php
Last commit: Fri Feb 17 02:02:18 2023 +0100 Jan Dankert Refactoring: Script-context should be the same in all environments; New: DslPdf for creating PDF with scriptbox ;)
1 <?php 2 3 namespace dsl\executor; 4 5 use dsl\DslAstParser; 6 use dsl\DslException; 7 use dsl\DslLexer; 8 use dsl\DslRuntimeException; 9 use dsl\standard\ArrayWrapper; 10 use dsl\standard\NumberInstance; 11 use dsl\standard\NumberWrapper; 12 use dsl\standard\Script; 13 use dsl\standard\ArrayInstance; 14 use dsl\standard\DateWrapper; 15 use dsl\standard\MathWrapper; 16 use dsl\standard\StringInstance; 17 use dsl\standard\StringWrapper; 18 use dsl\standard\System; 19 use dsl\standard\Writer; 20 use dsl\standard\WriteWrapper; 21 22 class DslInterpreter 23 { 24 /** 25 * Execution context. 26 * 27 * @var array 28 */ 29 private $context = []; 30 31 /** 32 * Holds a reference to the write()-Function for getting the output buffer after execution. 33 * @var Writer 34 */ 35 private $writer; 36 private $flags; 37 38 const FLAG_SHOW_ERROR = 1; 39 const FLAG_SHOW_TRACE = 2; 40 const FLAG_THROW_ERROR = 4; 41 const FLAG_DEBUG = 8; 42 const FLAG_SECURE = 16; 43 44 private static $secure = true; 45 46 public function __construct( $flags = self::FLAG_SHOW_ERROR + self::FLAG_SECURE ) 47 { 48 $this->flags = $flags; 49 50 self::$secure = boolval($this->flags & self::FLAG_SECURE ); 51 52 $this->addStandardContext(); 53 } 54 55 /** 56 * adds an external context to the interpreter environment. 57 * 58 * @param $context [] 59 */ 60 public function addContext($context ) { 61 $this->context = array_merge( $this->context, $context ); 62 } 63 64 65 /** 66 * Parses and runs the DSL code. 67 * 68 * @param $code String Script-Code 69 * @throws DslException 70 * @return mixed value of last return statement (if any) 71 */ 72 public function runCode( $code ) { 73 74 // Step 1: Splitting the source code into tokens (the "Lexer") 75 $lexer = new DslLexer(); 76 $token = $lexer->tokenize( $code ); 77 78 // Step 2: Creating a syntax tree (abstract syntax tree, AST). 79 try { 80 81 $parser = new DslAstParser(); 82 $parser->parse( $token ); 83 84 //if ( $this->flags & self::FLAG_DEBUG ) 85 // it has no security impact, so lets do it always. 86 $this->addContext( 87 [ 'Script' => new Script( $token,$parser->rootStatement ) ] 88 ); 89 90 // Step 3: Executing the syntax tree. 91 return $parser->execute( $this->context ); 92 } catch ( \Exception $e ) { 93 if ( $this->flags & self::FLAG_SHOW_ERROR ) { 94 if ( $this->flags & self::FLAG_SHOW_TRACE ) 95 $this->writer->buffer .= $e->__toString(); 96 else 97 $this->writer->buffer .= $e->getMessage(); 98 } 99 if ( $this->flags & self::FLAG_THROW_ERROR ) 100 throw new DslRuntimeException('Script runtime error',0,$e); 101 } 102 } 103 104 105 /** 106 * Gets the output which was written by the code. 107 * 108 * @return mixed 109 */ 110 public function getOutput() { 111 112 return $this->writer->buffer; 113 } 114 115 /** 116 * @return bool 117 */ 118 public static function isSecure() { 119 return self::$secure; 120 } 121 122 /** 123 * Adding the standard context. 124 * 125 * @return void 126 */ 127 private function addStandardContext() 128 { 129 // Standard-Globals 130 $this->addContext( [ 131 132 // Standard JS objects 133 'Math' => new MathWrapper(), 134 'Array' => new ArrayWrapper(), 135 'String' => new StringWrapper(), 136 'Number' => new NumberWrapper(), 137 'Date' => new DateWrapper(), 138 139 // Custom Scriptbox objects 140 'System' => new System(), 141 'write' => $this->writer = new Writer(), 142 'writeln' => new WriteWrapper( $this->writer,"\n" ), 143 'print' => new WriteWrapper( $this->writer,'' ), 144 'println' => new WriteWrapper( $this->writer,"\n" ), 145 ] ); 146 } 147 }
Downloadmodules/dsl/executor/DslInterpreter.class.php
History Fri, 17 Feb 2023 02:02:18 +0100 Jan Dankert Refactoring: Script-context should be the same in all environments; New: DslPdf for creating PDF with scriptbox ;) Tue, 19 Jul 2022 00:10:00 +0200 Jan Dankert New: Scripting language: Ignore Keyword "new"; Support for Calling object constructors; Splitting objects into an instance and a wrapper. Fri, 1 Jul 2022 18:09:05 +0200 Jan Dankert New: Bugfixes and much more string and array functions for the DSL. Mon, 27 Jun 2022 01:11:02 +0200 Jan Dankert New: Secure Flag for Script Interpreter which is enabled by default. Mon, 27 Jun 2022 00:40:42 +0200 Jan Dankert New: Marker interface 'Scriptable', Proxy class for MQTT, help() method in Scripts. Sun, 26 Jun 2022 12:51:07 +0200 Jan Dankert New: DSL can be controlled by flags; support for error messages; support for negativ numbers. Thu, 2 Jun 2022 01:50:05 +0200 Jan Dankert Refactoring: DSL Interpreter is now using a write buffer Wed, 1 Jun 2022 00:11:40 +0200 Jan Dankert New: DSL as a filter for number values Sun, 29 May 2022 01:13:27 +0200 Jan Dankert New: DSL with support for functions Sat, 28 May 2022 18:00:13 +0200 Jan Dankert New: DSL with a much better syntax parsing and support for assignments, conditions, ...