File modules/dsl/ast/DslStatementList.class.php

Last commit: Tue Jul 19 00:10:00 2022 +0200	Jan Dankert	New: Scripting language: Ignore Keyword "new"; Support for Calling object constructors; Splitting objects into an instance and a wrapper.
1 <?php 2 3 namespace dsl\ast; 4 5 use dsl\DslParserException; 6 use dsl\DslToken; 7 8 class DslStatementList extends DslElement implements DslStatement 9 { 10 private $statements = []; 11 12 private $functions = []; 13 14 public function __construct($tokenList) 15 { 16 $this->parse($tokenList); 17 } 18 19 /** 20 * @param $tokens DslToken[] 21 * @throws DslParserException 22 */ 23 public function parse($tokens) 24 { 25 $this->parseTokens($tokens); 26 } 27 28 public function execute( & $context) 29 { 30 // Auto hoisting for functions: Add functions to context. 31 $context = array_merge( $context, $this->functions ); 32 33 foreach ($this->statements as $statement) { 34 35 $value = $statement->execute($context); 36 37 if ($statement instanceof DslReturn) 38 return $value; // Return to the caller 39 } 40 41 return null; 42 } 43 44 45 46 /** 47 * @param $tokens DslToken[] 48 * @throws DslParserException 49 */ 50 public function parseTokens($tokens) 51 { 52 while (true) { 53 $token = array_shift($tokens); 54 55 if ( ! $token ) 56 return; 57 58 switch ($token->type) { 59 60 case DslToken::T_STATEMENT_END: 61 // maybe an empty statement? 62 break; 63 64 case DslToken::T_OPERATOR: 65 throw new DslParserException('Unexpected operator', $token->lineNumber); 66 case DslToken::T_BRACKET_CLOSE: 67 throw new DslParserException('Unexpected closing group', $token->lineNumber); 68 case DslToken::T_BLOCK_END: 69 throw new DslParserException('Unexpected ending of an block', $token->lineNumber); 70 case DslToken::T_NEGATION: 71 throw new DslParserException('Unexpected negation', $token->lineNumber); 72 case DslToken::T_DOT: 73 throw new DslParserException('Unexpected dot', $token->lineNumber); 74 75 case DslToken::T_FUNCTION: 76 77 $nameToken = array_shift( $tokens ); 78 if ($nameToken->type != DslToken::T_STRING) 79 throw new DslParserException('function must have a name', $token->lineNumber); 80 $name = $nameToken->value; 81 82 $functionCallOp = array_shift($tokens); 83 if ( $functionCallOp->type != DslToken::T_OPERATOR || $functionCallOp->value != '$' ) 84 throw new DslParserException('function \''.$name.'\' must have a function signature'); 85 86 $functionParameter = $this->getGroup($tokens); 87 $functionBlock = $this->getBlock($tokens); 88 89 $this->functions[ $name ] = new DslFunction( $functionParameter, $functionBlock ); 90 91 break; 92 93 case DslToken::T_IF: 94 $condition = $this->getGroup($tokens); 95 $positiveBlock = $this->getStatementOrBlock($tokens); 96 $nextToken = array_shift($tokens); 97 if ($nextToken && $nextToken->type == DslToken::T_ELSE) { 98 $negativeBlock = $this->getStatementOrBlock($tokens); 99 } else { 100 $negativeBlock = []; 101 array_unshift($tokens, $nextToken); 102 } 103 $this->statements[] = new DslIf($condition, $positiveBlock, $negativeBlock); 104 break; 105 106 case DslToken::T_NEW: 107 case DslToken::T_LET: 108 break; // ignore these statements 109 110 case DslToken::T_NULL: 111 $this->statements[] = new DslNull(); 112 break; 113 114 case DslToken::T_TRUE: 115 $this->statements[] = new DslTrue(); 116 break; 117 118 case DslToken::T_FALSE: 119 $this->statements[] = new DslFalse(); 120 break; 121 122 case DslToken::T_FOR: 123 $forGroup = $this->getGroup( $tokens ); 124 $forBlock = $this->getStatementOrBlock( $tokens ); 125 126 //echo "<h5>Forgroup:</h5><pre>"; var_export( $forGroup); echo "</pre>"; 127 128 $varName = array_shift( $forGroup ); 129 if ( $varName == null || $varName->type != DslToken::T_STRING ) 130 throw new DslParserException('for loop variable missing'); 131 $ofName = array_shift( $forGroup ); 132 if ( $ofName == null || $ofName->type != DslToken::T_STRING || strtolower($ofName->value) != 'of' ) 133 throw new DslParserException('missing \'of\' in for loop'); 134 135 $this->statements[] = new DslFor( $varName->value, $forGroup, $forBlock ); 136 break; 137 138 case DslToken::T_RETURN: 139 $returnTokens = $this->getSingleStatement( $tokens ); 140 $this->statements[] = new DslReturn( $returnTokens ); 141 break; 142 143 case DslToken::T_THROW: 144 $returnTokens = $this->getSingleStatement($tokens ); 145 $this->statements[] = new DslThrow( $returnTokens ); 146 break; 147 148 case DslToken::T_TEXT: 149 case DslToken::T_NUMBER: 150 case DslToken::T_STRING: 151 array_unshift( $tokens, $token ); 152 $statementTokens = $this->getSingleStatement( $tokens ); 153 154 $this->statements[] = new DslExpression( $statementTokens ); 155 break; 156 157 default: 158 throw new DslParserException('Unknown token of type '.$token->type,$token->lineNumber ); 159 } 160 161 } 162 163 } 164 165 166 }
Download modules/dsl/ast/DslStatementList.class.php
History 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. Sun, 26 Jun 2022 15:46:54 +0200 Jan Dankert Fix: Another, little better, hack for parameterless functions. Shunting yard seems to be unable to handle empty parentheses. Tue, 7 Jun 2022 23:30:20 +0200 Jan Dankert New: DSL is now supporting throw statements. Mon, 6 Jun 2022 13:35:56 +0200 Jan Dankert Change: Completely ignoring let,var,const statements. Wed, 1 Jun 2022 00:11:40 +0200 Jan Dankert New: DSL as a filter for number values Sun, 29 May 2022 16:56:40 +0200 Jan Dankert New: DSL with support for functions with return values, full arithmetic, object properties 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, ... Wed, 25 May 2022 22:47:17 +0200 Jan Dankert New: DSL (domain specific language) for code elements. The old way with PHP code ist not sandboxed and unsecure. This approach is a minimalistic, javascript-like, scripting engine. For now only simple function calls are possible, for example: alert("example");