DslStatementList.class.php (4484B)
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_LET: 107 break; 108 109 case DslToken::T_NULL: 110 $this->statements[] = new DslNull(); 111 break; 112 113 case DslToken::T_TRUE: 114 $this->statements[] = new DslTrue(); 115 break; 116 117 case DslToken::T_FALSE: 118 $this->statements[] = new DslFalse(); 119 break; 120 121 case DslToken::T_FOR: 122 $forGroup = $this->getGroup( $tokens ); 123 $forBlock = $this->getStatementOrBlock( $tokens ); 124 125 //echo "<h5>Forgroup:</h5><pre>"; var_export( $forGroup); echo "</pre>"; 126 127 $varName = array_shift( $forGroup ); 128 if ( $varName == null || $varName->type != DslToken::T_STRING ) 129 throw new DslParserException('for loop variable missing'); 130 $ofName = array_shift( $forGroup ); 131 if ( $ofName == null || $ofName->type != DslToken::T_STRING || strtolower($ofName->value) != 'of' ) 132 throw new DslParserException('missing \'of\' in for loop'); 133 134 $this->statements[] = new DslFor( $varName->value, $forGroup, $forBlock ); 135 break; 136 137 case DslToken::T_RETURN: 138 $returnTokens = $this->getSingleStatement( $tokens ); 139 $this->statements[] = new DslReturn( $returnTokens ); 140 break; 141 142 case DslToken::T_THROW: 143 $returnTokens = $this->getSingleStatement($tokens ); 144 $this->statements[] = new DslThrow( $returnTokens ); 145 break; 146 147 case DslToken::T_TEXT: 148 case DslToken::T_NUMBER: 149 case DslToken::T_STRING: 150 array_unshift( $tokens, $token ); 151 $statementTokens = $this->getSingleStatement( $tokens ); 152 153 $this->statements[] = new DslExpression( $statementTokens ); 154 break; 155 156 default: 157 throw new DslParserException('Unknown token of type '.$token->type,$token->lineNumber ); 158 } 159 160 } 161 162 } 163 164 165 }