openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

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 }