openrat-cms

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

commit c1f436bc9b635f49dc5ba565ae218bd69534c255
parent cd284ba56a2aea2b9293e9f2528fb92f9cf06c4e
Author: Jan Dankert <develop@jandankert.de>
Date:   Sun, 29 May 2022 16:56:40 +0200

New: DSL with support for functions with return values, full arithmetic, object properties

Diffstat:
Mmodules/cms/generator/dsl/DslDocument.class.php | 1+
Mmodules/cms/generator/dsl/DslPage.class.php | 8++++++++
Mmodules/cms/ui/themes/default/html/views/element/advanced.php | 5++++-
Mmodules/cms/ui/themes/default/html/views/element/advanced.tpl.src.xml | 2+-
Mmodules/dsl/DslLexer.class.php | 55+++++++++++++++++++++++++++++++++++++++++++++++++++----
Mmodules/dsl/ast/DslAssignment.class.php | 13+++++--------
Mmodules/dsl/ast/DslElement.class.php | 2+-
Mmodules/dsl/ast/DslExpression.class.php | 237+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mmodules/dsl/ast/DslFor.class.php | 6++++--
Mmodules/dsl/ast/DslFunction.class.php | 8+++++---
Mmodules/dsl/ast/DslFunctionCall.class.php | 51++++++++++++++++++++++++++++++---------------------
Mmodules/dsl/ast/DslInteger.class.php | 2+-
Mmodules/dsl/ast/DslOperation.class.php | 30+++++++++++++++++++++++++++---
Amodules/dsl/ast/DslProperty.class.php | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmodules/dsl/ast/DslReturn.class.php | 1+
Amodules/dsl/ast/DslSequence.class.php | 42++++++++++++++++++++++++++++++++++++++++++
Mmodules/dsl/ast/DslStatementList.class.php | 37+++++++++++--------------------------
17 files changed, 429 insertions(+), 123 deletions(-)

diff --git a/modules/cms/generator/dsl/DslDocument.class.php b/modules/cms/generator/dsl/DslDocument.class.php @@ -6,6 +6,7 @@ use dsl\context\DslObject; class DslDocument implements DslObject { + public $write; public function write( $text ) { echo $text; } diff --git a/modules/cms/generator/dsl/DslPage.class.php b/modules/cms/generator/dsl/DslPage.class.php @@ -22,4 +22,12 @@ class DslPage implements DslObject $this->id = $page->getId(); } + /** + * @return array + * @throws \util\exception\ObjectNotFoundException + */ + public function elements() { + return $this->page->getElementIds(); + } + } \ No newline at end of file diff --git a/modules/cms/ui/themes/default/html/views/element/advanced.php b/modules/cms/ui/themes/default/html/views/element/advanced.php @@ -246,7 +246,10 @@ <section class="<?php echo O::escapeHtml('or-fieldset') ?>"><?php echo O::escapeHtml('') ?> <h3 class="<?php echo O::escapeHtml('or-fieldset-label') ?>"><?php echo O::escapeHtml(''.@O::lang('EL_PROP_code').'') ?></h3> <div class="<?php echo O::escapeHtml('or-fieldset-value') ?>"><?php echo O::escapeHtml('') ?> - <textarea name="<?php echo O::escapeHtml('code') ?>" class="<?php echo O::escapeHtml('or-input or-inputarea') ?>"><?php echo O::escapeHtml(''.@$code.'') ?></textarea> + <div><?php echo O::escapeHtml('') ?> + <textarea name="<?php echo O::escapeHtml('code') ?>" data-extension="<?php echo O::escapeHtml('') ?>" data-mimetype="<?php echo O::escapeHtml('') ?>" data-mode="<?php echo O::escapeHtml('js') ?>" class="<?php echo O::escapeHtml('or-input or-editor or-code-editor') ?>"><?php echo O::escapeHtml(''.@$code.'') ?></textarea> + <trix-editor input="<?php echo O::escapeHtml('code') ?>"><?php echo O::escapeHtml('') ?></trix-editor> + </div> </div> </section> <?php } ?> diff --git a/modules/cms/ui/themes/default/html/views/element/advanced.tpl.src.xml b/modules/cms/ui/themes/default/html/views/element/advanced.tpl.src.xml @@ -125,7 +125,7 @@ </if> <if present="code"> <fieldset class="line" label="${message:EL_PROP_code}"> - <inputarea name="code" rows="35"/> + <editor name="code" type="code" mode="js" /> </fieldset> </if> </group> diff --git a/modules/dsl/DslLexer.class.php b/modules/dsl/DslLexer.class.php @@ -18,6 +18,45 @@ class DslLexer 'new' => DslToken::T_NEW, ]; + const UNUSED_KEYWORDS = [ + 'null', + 'true', + 'false', + 'implements', + 'interface', + 'package', + 'private', + 'protected', + 'public', + 'static', + 'in', + 'do', + 'new', + 'try', + 'this', + 'case', + 'void', + 'with', + 'enum', + 'while', + 'break', + 'catch', + 'throw', + 'yield', + 'class', + 'super', + 'typeof', + 'delete', + 'switch', + 'export', + 'import', + 'default', + 'finally', + 'extends', + 'continue', + 'debugger', + 'instanceof', + ]; /** * @param $code * @return array(DslToken) @@ -120,6 +159,9 @@ class DslLexer } else { $type = DslToken::T_STRING; + if ( array_key_exists($value,self::UNUSED_KEYWORDS ) ) + throw new DslParserException( 'use of reserved word \''.$value.'\' is not allowed.'); + if ( array_key_exists($value,self::KEYWORDS ) ) $type = self::KEYWORDS[$value]; // it is a keyword @@ -148,12 +190,13 @@ class DslLexer continue; } - if ( $char == '+' || $char == '-' || $char == '/' || $char == '*' || $char == '=' || $char == '|' || $char == '&' ) { + $operatorChars = ['+' ,'-','/' ,'*','=','|','&',',','.' ]; + if ( in_array($char,$operatorChars)) { $value = $char; while( true ) { $char = array_shift( $chars ); - if ( $char == '+' || $char == '-' || $char == '/' || $char == '*' || $char == '=' || $char == '|' || $char == '&' ) { + if ( in_array($char,$operatorChars) ) { $value .= $char; } else { $type = DslToken::T_OPERATOR; @@ -175,8 +218,12 @@ class DslLexer $this->addToken( $line,DslToken::T_DOT,$char); elseif ( $char == ',' ) $this->addToken( $line,DslToken::T_COMMA,$char); - elseif ( $char == '(' ) + + elseif ( $char == '(' ) { + if ( end( $this->token)->type == DslToken::T_STRING) + $this->addToken( $line, DslToken::T_OPERATOR,'$'); // function call $this->addToken( $line,DslToken::T_BRACKET_OPEN,$char); + } elseif ( $char == ')' ) $this->addToken( $line,DslToken::T_BRACKET_CLOSE,$char); elseif ( $char == '{' ) @@ -184,7 +231,7 @@ class DslLexer elseif ( $char == '}' ) $this->addToken( $line,DslToken::T_BLOCK_END,$char); else { - throw new \Exception('Unknown character \''.$char.'\' on line '.$line.'.'); + throw new DslParserException('Unknown character \''.$char.'\'',$line); } } diff --git a/modules/dsl/ast/DslAssignment.class.php b/modules/dsl/ast/DslAssignment.class.php @@ -13,19 +13,16 @@ class DslAssignment implements DslStatement /** * DslAssignment constructor. - * @param $target DslToken[] - * @param $value DslToken[] + * @param $target DslStatement + * @param $value DslStatement * @throws DslParserException */ public function __construct( $target, $value ) { - echo "<h5>Assignment:</h5><pre>"; var_export( $target ); var_export($value); echo "</pre>"; + //echo "<h5>Assignment:</h5><pre>"; var_export( $target ); var_export($value); echo "</pre>"; - if ( sizeof( $target ) != 1 ) - throw new DslParserException('Assignment only possible for variables.'); - - $this->target = new DslVariable( $target[0]->value ); - $this->value = new DslExpression( $value ); + $this->target = $target; + $this->value = $value; } /** diff --git a/modules/dsl/ast/DslElement.class.php b/modules/dsl/ast/DslElement.class.php @@ -134,7 +134,7 @@ class DslElement $act = []; foreach ( $functionParameter as $token ) { - if ( $token->type == DslToken::T_COMMA ) { + if ( $token->type == DslToken::T_OPERATOR && $token->value == ',' ) { $parts[] = $act; $act = []; // Cleanup continue; diff --git a/modules/dsl/ast/DslExpression.class.php b/modules/dsl/ast/DslExpression.class.php @@ -2,6 +2,9 @@ namespace dsl\ast; +define('LEFT', 0); +define('RIGHT', 1); + use dsl\DslParserException; use dsl\DslToken; @@ -23,81 +26,211 @@ class DslExpression extends DslElement implements DslStatement return $this->value->execute( $context ); } + /** + * @param DslToken[] $tokens + * @throws DslParserException + */ public function parse($tokens) { - echo "<h5>Expression:</h5><pre>"; var_export( $tokens ); echo "</pre>"; + //echo "<h5>Expression:</h5><pre>"; var_export( $tokens ); echo "</pre>"; if ( ! $tokens ) { $this->value = new DslNull(); return; } - - // Split the expression on operators - foreach ( array_reverse(['*','/','-','+','!','||','&&','>','>=','<=','<']) as $tokenValue ) { - list( $left,$right ) = $this->splitTokenOnOperator( $tokens, $tokenValue ); - if ( sizeof($right ) > 0 ) { - $this->value = new DslOperation( $tokenValue,$left,$right ); - return; - } - } + $this->parseExpression( $tokens ); + // Groups + } - if ( sizeof($tokens) == 1) { - $token = $tokens[0]; - switch( $token->type ) { - case DslToken::T_TEXT: - $this->value = new DslString( $token->value ); - break; - case DslToken::T_STRING: - $this->value = new DslVariable( $token->value ); - break; - case DslToken::T_NUMBER: - $this->value = new DslInteger( $token->value ); - break; - default: - throw new DslParserException('unknown token '.$token->type.' in expression',$token->lineNumber); - } + /** + * Parsing an expression using the shunting yard algorithm. + * + * Precedences see https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#assoziativit%C3%A4t + * @param DslToken[] $tokens + * @throws DslParserException + */ + private function parseExpression( $tokens ) + { + $precedence = [ + ',' => 2, + '=' => 3, + '+=' => 3, + '-=' => 3, + '||' => 5, + '&&' => 6, + '==' => 10, + '!=' => 10, + '<' => 11, + '<=' => 11, + '>' => 11, + '>=' => 11, + '+' => 13, + '-' => 13, + '/' => 14, + '*' => 14, + '%' => 14, + '**' => 15, + '!' => 16, + '$' => 19, // function call, provided by the lexer + '.' => 19, + ]; + + $assoc = [ + ',' => LEFT, + '=' => RIGHT, + '-=' => RIGHT, + '+=' => RIGHT, + '||' => LEFT, + '&&' => LEFT, + '==' => LEFT, + '!=' => LEFT, + '<' => LEFT, + '<=' => LEFT, + '> ' => LEFT, + '>=' => LEFT, + '+' => LEFT, + '-' => LEFT, + '/' => LEFT, + '*' => LEFT, + '%' => LEFT, + '^' => RIGHT, + '!' => RIGHT, + '**' => RIGHT, + '.' => RIGHT, + '$' => LEFT, + ]; + + + // for the purpose of comparing only; it's forced to top priority explicitly + $precedence['('] = 0; + $precedence[')'] = 0; + + $output_queue = array(); + $operator_stack = array(); + + if ( $tokens instanceof DslStatement ) { + + $this->value = $tokens; return; } - while( true ) { + if ( $tokens instanceof DslToken ) + $tokens = [$tokens]; - $token = array_shift( $tokens ); + if ( ! is_array($tokens)) echo "tokens ist kein array, aber ".get_class($tokens); - if ( $token == null ) { - break; - } + // while there are tokens to be read: + while ($tokens) { + // read a token. + $token = array_shift($tokens); - if ( $token->type == DslToken::T_STRING ) - { - $nextToken = array_shift( $tokens ); - if ( $nextToken && $nextToken->type == DslToken::T_BRACKET_OPEN ) - { - array_unshift( $tokens,$nextToken ); + if ($token->type == DslToken::T_OPERATOR) { - $parameterGroup = $this->getGroup( $tokens ); - $splittedParameters = $this->splitByComma( $parameterGroup ); + // while there is an operator at the top of the operator stack with + // greater than or equal to precedence: + while ($operator_stack && + $precedence[end($operator_stack)->value] >= $precedence[$token->value] + $assoc[$token->value]) { + // pop operators from the operator stack, onto the output queue. - $this->value = new DslFunctionCall( $token->value,$splittedParameters ); - return; + $left = array_pop( $output_queue ); + $right = array_pop( $output_queue ); + $output_queue[] = $this->createNode( array_pop($operator_stack),$left,$right ); + } + // push the read operator onto the operator stack. + $operator_stack[] = $token; + + // if the token is a left bracket (i.e. "("), then: + } elseif ($token->value === '(') { + // push it onto the operator stack. + $operator_stack[] = $token; + + // if the token is a right bracket (i.e. ")"), then: + } elseif ($token->value === ')') { + // while the operator at the top of the operator stack is not a left bracket: + while (end($operator_stack)->value !== '(') { + // pop operators from the operator stack onto the output queue. + $left = array_pop( $output_queue ); + $right = array_pop( $output_queue ); + $output_queue[] = $this->createNode( array_pop($operator_stack),$left,$right ); + + // /* if the stack runs out without finding a left bracket, then there are + // mismatched parentheses. */ + if (!$operator_stack) { + throw new DslParserException("Mismatched parentheses!"); + } } + + // pop the left bracket from the stack. + array_pop($operator_stack); + } + elseif // if the token is a number, then push it to the output queue. + (true) { + $output_queue[] = $this->tokenToStatement( $token ); + + // if the token is an operator, then: + } else { + throw new DslParserException( 'Unexpected token '.$token->value, $token->lineNumber); + } + } // if there are no more tokens to read: + + // while there are still operator tokens on the stack: + while ($operator_stack) { + $token = array_pop($operator_stack); + + // if the operator token on the top of the stack is a bracket, then + // there are mismatched parentheses. + if ($token->type == DslToken::T_OPERATOR && $token->value == '(') { + throw new DslParserException( "Mismatched parentheses"); + } + // pop the operator onto the output queue. + $left = array_pop( $output_queue ); + $right = array_pop( $output_queue ); + $output_queue[] = $this->createNode( $token,$left,$right ); } - $this->value = new DslNull(); - } - private function splitTokenOnOperator( $tokens, $operatorValue ) { - // Split the expression on operators - $leftToken = []; + //echo "<h5>Output queue:</h5><pre>"; var_export( $output_queue ); echo "</pre>"; + $this->value = $output_queue[0]; + } + + /** + * @param $op DslToken + * @param $left + * @param $right + * @throws DslParserException + */ + private function createNode($op, $left, $right) + { + if ( $op->value == '=' ) + return new DslAssignment( $right,$left ); + if ( $op->value == ',' ) + return new DslSequence( $right,$left ); + if ( $op->value == '.' ) + return new DslProperty( $right, $left ); + if ( $op->value == '$' ) + return new DslFunctionCall( $right, $left ); + else + return new DslOperation( $op->value,$right,$left ); + } - while( true ) { - $token = array_shift($tokens); - if ( $token == null ) - return [ $leftToken,[] ]; - if ( $token->type == DslToken::T_OPERATOR && $token->value == $operatorValue ) - return [ $leftToken,$tokens ]; - $leftToken[] = $token; + /** + * @param $token DslToken + */ + private function tokenToStatement($token) + { + switch( $token->type ) { + case DslToken::T_NUMBER: + return new DslInteger( $token->value ); + case DslToken::T_TEXT: + return new DslString( $token->value ); + case DslToken::T_STRING: + return new DslVariable( $token->value ); + case DslToken::T_DOT: + return new DslProperty( $token->value ); + default: + throw new DslParserException('Unknown token '.$token->value,$token->lineNumber); } } } \ No newline at end of file diff --git a/modules/dsl/ast/DslFor.class.php b/modules/dsl/ast/DslFor.class.php @@ -27,13 +27,15 @@ class DslFor implements DslStatement public function execute( & $context ) { + $list = $this->list->execute( $context ); + if ( !is_array( $list ) ) throw new DslRuntimeException('for value is not a list'); $copiedContext = $context; - foreach( $list as $blockVar ) { - $copiedContext[ $this->name ] = $blockVar; + foreach( $list as $loopVar ) { + $copiedContext[ $this->name ] = $loopVar; $this->statements->execute( $copiedContext ); } } diff --git a/modules/dsl/ast/DslFunction.class.php b/modules/dsl/ast/DslFunction.class.php @@ -35,15 +35,17 @@ class DslFunction extends DslElement implements DslStatement * DslFunction constructor. * * @param $functionParameter DslToken[] - * @param $functionBody DslToken[] + * @param $functionBody DslStatement * @throws DslParserException */ public function __construct( $functionParameter, $functionBody ) { - $this->parameters = []; + //$this->parameters = $functionParameter; + + //var_export($this->splitByComma( $functionParameter )); foreach( $this->splitByComma( $functionParameter ) as $parameter ) { if ( sizeof($parameter) != 1 ) - throw new DslParserException('function parameter must be a name'); + throw new DslParserException('function parameter must be a single name'); $nameToken = $parameter[0]; if ( $nameToken->type != DslToken::T_STRING ) throw new DslParserException('function parameter must be a name'); diff --git a/modules/dsl/ast/DslFunctionCall.class.php b/modules/dsl/ast/DslFunctionCall.class.php @@ -18,11 +18,7 @@ class DslFunctionCall implements DslStatement public function __construct($name, $parameters) { $this->name = $name; - - $this->parameters = []; - - foreach( $parameters as $parameter ) - $this->parameters[] = new DslExpression( $parameter ); + $this->parameters = $parameters; } @@ -31,36 +27,49 @@ class DslFunctionCall implements DslStatement */ public function execute(& $context ) { - if ( ! array_key_exists( $this->name, $context ) ) - throw new DslRuntimeException('function \''.$this->name.'\' does not exist.'); + //var_export($this->name); + $function = $this->name->execute( $context ); + + + //echo "name is $name"; + //if ( ! array_key_exists( $name, $context ) ) + // throw new DslRuntimeException('function \''.$this->name.'\' does not exist.'); +// +// $function = $context[$name]; + + $parameterValues = $this->parameters->execute( $context ); + + // if there is only 1 parameter it must be converted to an array. + // if there are more than 1 parameter, it is already a sequence + if ( ! is_array($parameterValues)) $parameterValues = array($parameterValues); - $function = $context[$this->name]; if ( $function instanceof \dsl\context\DslFunction ) { // call "external" native function - $parameterValues = array_map( function( $parameter ) use ($context) { - return $parameter->execute( $context ); - }, $this->parameters ); return call_user_func_array(array($function,'execute'),$parameterValues ); } elseif ( $function instanceof DslFunction ) { - // call DSL function - if ( sizeof( $function->parameters ) != sizeof($this->parameters) ) - throw new DslRuntimeException('function call parameter count must match the function declaration'); + + $parameters = $function->parameters; + + if ( sizeof($parameters) != sizeof($parameterValues) ) + throw new DslRuntimeException('function call has '.sizeof($parameterValues).' parameters but the function has '.sizeof($parameters).' parameters'); // Put all function parameters to the function context. - $parameters = array_combine( $function->parameters, $this->parameters ); + $parameterContext = array_combine( $parameters, $parameterValues ); + $subContext = array_merge( $context,$parameterContext ); - $cloneContext = $context; - foreach( $parameters as $name=>$parameter ) { - $cloneContext[ $name ] = $parameter->execute( $context ); - } - return $function->execute( $cloneContext ); + return $function->execute( $subContext ); + + } + elseif ( is_callable($function) ) { + //var_export( call_user_func_array( $function, $parameterValues) ); + return call_user_func_array( $function, $parameterValues); } else - throw new DslRuntimeException('function \''.$this->name.'\' is not callable.'); + throw new DslRuntimeException('function is not callable'.var_export($function)); } public function parse($tokens) diff --git a/modules/dsl/ast/DslInteger.class.php b/modules/dsl/ast/DslInteger.class.php @@ -18,7 +18,7 @@ class DslInteger implements DslStatement public function execute( & $context ) { - return $this->number; + return intval($this->number); } public function parse($tokens) diff --git a/modules/dsl/ast/DslOperation.class.php b/modules/dsl/ast/DslOperation.class.php @@ -36,13 +36,13 @@ class DslOperation implements DslStatement switch( $this->operator ) { case '+': - if ( is_string($left) ) + if ( is_string($left) ) return $left . $right; else - return $left + $right; + return intval($left) + intval($right); case '-': - return $left - $right; + return intval($left) - intval($right); case '*': return $left * $right; @@ -50,6 +50,30 @@ class DslOperation implements DslStatement case '/': return $left / $right; + case '==': + return $left == $right; + case '!=': + return $left != $right; + case '<': + return $left < $right; + case '<=': + return $left <= $right; + case '>': + return $left > $right; + case '>=': + return $left >= $right; + + case '||': + return $left || $right; + case '&&': + return $left && $right; + + case '%': + return $left % $right; + + case '!': + return ! $left; + default: throw new DslRuntimeException('Unknown operator \''.$this->operator.'\''); } diff --git a/modules/dsl/ast/DslProperty.class.php b/modules/dsl/ast/DslProperty.class.php @@ -0,0 +1,51 @@ +<?php + +namespace dsl\ast; + +use dsl\DslRuntimeException; + +class DslProperty implements DslStatement +{ + public $variable; + public $property; + + /** + * DslProperty constructor. + * @param $variable + * @param $property + */ + public function __construct($variable, $property) + { + $this->variable = $variable; + $this->property = $property; + } + + + /** + * @param array $context + * @return mixed + * @throws DslRuntimeException + */ + public function execute( & $context ) { + + $object = $this->variable->execute( $context ); + + if ( ! is_object( $object ) ) + throw new DslRuntimeException('is no object'); + + $objectContext = get_object_vars( $object ); + + // copy object methods to the object context to make them callable. + foreach( get_class_methods( $object ) as $method ) { + $objectContext[ $method ] = function() use ($method, $object) { + return call_user_func_array( array($object,$method),func_get_args() ); + }; + } + $prop = $this->property->execute( $objectContext ); + return $prop; + } + + public function parse($tokens) + { + } +} +\ No newline at end of file diff --git a/modules/dsl/ast/DslReturn.class.php b/modules/dsl/ast/DslReturn.class.php @@ -13,6 +13,7 @@ class DslReturn implements DslStatement public function execute( & $context ) { + return $this->value->execute( $context ); } public function parse($tokens) diff --git a/modules/dsl/ast/DslSequence.class.php b/modules/dsl/ast/DslSequence.class.php @@ -0,0 +1,41 @@ +<?php + +namespace dsl\ast; + +use dsl\DslRuntimeException; + +class DslSequence implements DslStatement +{ + public $left; + public $right; + + + /** + * DslSequence constructor. + * @param $left + * @param $right + */ + public function __construct($left, $right) + { + $this->left = $left; + $this->right = $right; + } + + + public function execute( & $context ) { + + // Creating a sequence + $left = $this->left->execute( $context ); + $right = $this->right->execute( $context ); + + // cast to array + if ( !is_array( $left ) ) $left = [$left ]; + if ( !is_array( $right) ) $right = [$right]; + + return array_merge( $left,$right); + } + + public function parse($tokens) + { + } +} +\ No newline at end of file diff --git a/modules/dsl/ast/DslStatementList.class.php b/modules/dsl/ast/DslStatementList.class.php @@ -77,6 +77,7 @@ class DslStatementList extends DslElement implements DslStatement throw new DslParserException('function must have a name', $token->lineNumber); $name = $nameToken->value; + $functionCallOp = array_shift($tokens); $functionParameter = $this->getGroup($tokens); $functionBlock = $this->getBlock($tokens); @@ -87,7 +88,7 @@ class DslStatementList extends DslElement implements DslStatement $condition = $this->getGroup($tokens); $positiveBlock = $this->getStatementOrBlock($tokens); $nextToken = array_shift($tokens); - if ($nextToken->type == DslToken::T_ELSE) { + if ($nextToken && $nextToken->type == DslToken::T_ELSE) { $negativeBlock = $this->getStatementOrBlock($tokens); } else { $negativeBlock = []; @@ -115,21 +116,21 @@ class DslStatementList extends DslElement implements DslStatement break; case DslToken::T_FOR: - $forGroup = $this->getGroup(); - $forBlock = $this->getStatementOrBlock(); + $forGroup = $this->getGroup( $tokens ); + $forBlock = $this->getStatementOrBlock( $tokens ); + + //echo "<h5>Forgroup:</h5><pre>"; var_export( $forGroup); echo "</pre>"; $varName = array_shift( $forGroup ); - if ( $varName->type != DslToken::T_STRING ) + if ( $varName == null || $varName->type != DslToken::T_STRING ) throw new DslParserException('for loop variable missing'); $ofName = array_shift( $forGroup ); - if ( $ofName->type != DslToken::T_STRING || strtolower($ofName->value) != 'or' ) + if ( $ofName == null || $ofName->type != DslToken::T_STRING || strtolower($ofName->value) != 'of' ) throw new DslParserException('missing \'of\' in for loop'); - $this->statements[] = new DslFor( $varName, $forGroup, $forBlock ); + $this->statements[] = new DslFor( $varName->value, $forGroup, $forBlock ); break; - case DslToken::T_NEW: - throw new DslParserException("new makes no sense without an assignment"); case DslToken::T_RETURN: $returnTokens = $this->getSingleStatement( $tokens ); $this->statements[] = new DslReturn( $returnTokens ); @@ -140,27 +141,11 @@ class DslStatementList extends DslElement implements DslStatement array_unshift( $tokens, $token ); $statementTokens = $this->getSingleStatement( $tokens ); - // we have to look if it is an assignment. - $assignmentTokens = []; - $expressionTokens = []; - foreach ( $statementTokens as $t ) { - if ( $t->type == DslToken::T_OPERATOR && $t->value == '=' ) { - $assignmentTokens = $expressionTokens; - $expressionTokens = []; - continue; - } - - $expressionTokens[] = $t; - } - - if ( $assignmentTokens ) - $this->statements[] = new DslAssignment( $assignmentTokens, $expressionTokens ); - else - $this->statements[] = new DslExpression( $expressionTokens ); + $this->statements[] = new DslExpression( $statementTokens ); break; default: - throw new DslParserException('Unknown token of type '+ $token->type ); + throw new DslParserException('Unknown token of type '.$token->type,$token->lineNumber ); } }