/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { $name = $this->block->name; // handle closing block if ($this->block->isClosingBlock) { // skip whitespace and comments $this->findNextElement(); if (!$cursor->match('}')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } $el = new ezcTemplateIfConditionTstNode($this->parser->source, $this->startCursor, $cursor); $el->name = 'if'; $el->isClosingBlock = true; $this->appendElement($el); return true; } $condition = null; $this->findNextElement(); if ($name != 'else') { if (!$this->parseRequiredType('Expression', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_EXPRESSION); } $condition = $this->lastParser->rootOperator; if ($condition instanceof ezcTemplateModifyingOperatorTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_MODIFYING_EXPRESSION_NOT_ALLOWED); } $this->findNextElement(); } if (!$cursor->match('}')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } $cb = new ezcTemplateConditionBodyTstNode($this->parser->source, $this->startCursor, $cursor); $cb->condition = $condition; $cb->name = $name; if ($name == 'if') { $el = new ezcTemplateIfConditionTstNode($this->parser->source, $this->startCursor, $cursor); $el->children[] = $cb; $el->name = 'if'; $this->appendElement($el); } else { $this->appendElement($cb); } return true; }
/** * Parses the null type. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { if (!$cursor->atEnd()) { if ($cursor->match("null")) { $literal = new ezcTemplateLiteralTstNode($this->parser->source, $this->startCursor, $cursor); $literal->value = null; $this->element = $literal; $this->appendElement($literal); return true; } } return false; }
/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { $element = new ezcTemplateLoopTstNode($this->parser->source, $this->startCursor, $cursor, $this->block->name); if ($this->block->isClosingBlock) { $element->isClosingBlock = true; } $this->findNextElement(); if (!$cursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $cursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } $this->appendElement($element); return true; }
/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { if ($this->block->name == "charset") { $charset = new ezcTemplateCharsetTstNode($this->parser->source, $this->startCursor, $cursor); $this->findNextElement(); if (!$this->parseOptionalType('String', null, false)) { throw new ezcTemplateSourceToTstParserException($this, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_STRING); } $charset->name = $this->lastParser->value; $this->findNextElement(); if (!$cursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $cursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } $this->appendElement($charset); return true; } return false; }
/** * Parses the variable types by looking for a dollar sign followed by an * identifier. The identifier is parsed by using ezcTemplateIdentifierSourceToTstParser. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { if (!$cursor->atEnd()) { if ($cursor->match('$')) { if ($cursor->current() == '#') { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_INVALID_VARIABLE_NAME, ezcTemplateSourceToTstErrorMessages::LNG_INVALID_NAMESPACE_ROOT_MARKER); } if ($cursor->current() == ':') { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_INVALID_VARIABLE_NAME, ezcTemplateSourceToTstErrorMessages::LNG_INVALID_NAMESPACE_MARKER); } if (!$this->parseRequiredType('Identifier', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_INVALID_VARIABLE_NAME, ezcTemplateSourceToTstErrorMessages::MSG_INVALID_IDENTIFIER); return false; } $this->variableName = $this->lastParser->identifierName; $variable = new ezcTemplateVariableTstNode($this->parser->source, $this->startCursor, $cursor); $variable->name = $this->variableName; $this->element = $variable; $this->appendElement($variable); return true; } } return false; }
/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { // Disable caching. // return false; if ($cursor->match("dynamic")) { $cacheNode = new ezcTemplateDynamicBlockTstNode($this->parser->source, $this->startCursor, $cursor); if ($this->block->isClosingBlock) { $cacheNode->isClosingBlock = true; } $this->appendElement($cacheNode); $this->findNextElement($cursor); if (!$cursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $cursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } return true; } $cacheNode = null; if ($cursor->match("cache_template")) { $this->parser->hasCacheBlocks = true; $cacheNode = new ezcTemplateCacheTstNode($this->parser->source, $this->startCursor, $cursor); $cacheNode->type = ezcTemplateCacheTstNode::TYPE_CACHE_TEMPLATE; } elseif ($cursor->match("cache_block")) { $this->parser->hasCacheBlocks = true; $cacheNode = new ezcTemplateCacheBlockTstNode($this->parser->source, $this->startCursor, $cursor); // $cacheNode->type = ezcTemplateCacheTstNode::TYPE_CACHE_BLOCK; if ($this->block->isClosingBlock) { $cacheNode->isClosingBlock = true; // Set closing block. $this->appendElement($cacheNode); $this->findNextElement($cursor); if (!$cursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $cursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } return true; } } else { return false; } // We do have an opening cache_block or cache_template. $this->findNextElement($cursor); while ($matches = $cursor->pregMatchComplete("#^([a-zA-Z_][a-zA-Z0-9_-]*)(?:[^a-zA-Z])#i")) { $name = $matches[1][0]; $cursor->advance(strlen($name)); $this->findNextElement($cursor); if ($name == "keys") { do { $this->findNextElement($cursor); if (!$this->parseOptionalType("Expression", $this->currentCursor, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_VARIABLE); } $cacheNode->keys[] = $this->lastParser->children[0]; $this->findNextElement($cursor); } while ($cursor->match(",")); // $this->parser->template->configuration->cacheSystem->appendCacheKeys( $values ); } elseif ($name == "ttl") { // The parameter has an expression. if (!$this->parseOptionalType('Expression', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_EXPRESSION); } if ($this->lastParser->rootOperator instanceof ezcTemplateModifyingOperatorTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_MODIFYING_EXPRESSION_NOT_ALLOWED); } // Append the parameter to the "namedParameters" array. $cacheNode->ttl = $this->lastParser->rootOperator; } else { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, "Unknown keyword: " . $name); } } $this->appendElement($cacheNode); $this->findNextElement($cursor); if (!$cursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $cursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } return true; }
/** * Parses the array types by looking for 'array(...)' and then using the * generic expression parser (ezcTemplateExpressionSourceToTstParser) to fetch the * keys and values. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { // skip whitespace and comments if (!$this->findNextElement()) { return false; } $name = $cursor->pregMatch("#^array[^\\w]#i", false); if ($name === false) { return false; } $lower = strtolower($name); if ($name !== $lower) { $this->findNonLowercase(); throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_ARRAY_NOT_LOWERCASE); } $cursor->advance(5); // skip whitespace and comments $this->findNextElement(); if (!$cursor->match('(')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_ROUND_BRACKET_OPEN); } $currentArray = array(); $currentKeys = array(); $expectItem = true; $elementNumber = 0; while (true) { // skip whitespace and comments if (!$this->findNextElement()) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_ROUND_BRACKET_CLOSE); } if ($cursor->current() == ')') { $cursor->advance(); $array = new ezcTemplateLiteralArrayTstNode($this->parser->source, $this->startCursor, $cursor); $array->keys = $currentKeys; $array->value = $currentArray; $this->element = $array; $this->appendElement($array); return true; } if (!$expectItem) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_ROUND_BRACKET_CLOSE_OR_COMMA); } // Check for type if (!$expectItem || !$this->parseRequiredType('Expression')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_LITERAL); } $this->findNextElement(); if ($cursor->match('=>')) { // Found the array key. Store it, and continue with the search for the value. $currentKeys[$elementNumber] = $this->lastParser->rootOperator; $this->findNextElement(); // We have the key => value syntax so we need to find the value if (!$this->parseRequiredType('Expression')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_LITERAL); } // Store the value. $currentArray[$elementNumber] = $this->lastParser->rootOperator; $elementNumber++; } else { // Store the value. $currentArray[$elementNumber] = $this->lastParser->rootOperator; $elementNumber++; } if ($this->lastParser->rootOperator instanceof ezcTemplateModifyingOperatorTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_MODIFYING_EXPRESSION_NOT_ALLOWED); } $this->findNextElement(); // We allow a comma after the key/value even if there are no more // entries. This is compatible with PHP syntax. if ($cursor->match(',')) { $this->findNextElement(); $expectItem = true; } else { $expectItem = false; } } }
/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { $el = new ezcTemplateTranslationTstNode($this->parser->source, $this->startCursor, $cursor); $this->findNextElement(); if (!$this->parseRequiredType('String', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_STRING); } $el->string = $this->lastParser->element; // empty keys and values before the loop, so that multiple vars statements can work $currentKeys = $currentArray = array(); $foundContext = $foundComment = false; $elementNr = 0; // the loop that parses context/comment/vars do { $foundSomething = false; $this->findNextElement(); // Check if we have a context if ($cursor->match('context')) { if ($foundContext) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->lastCursor, ezcTemplateSourceToTstErrorMessages::MSG_CONTEXT_DUPLICATE); } $this->findNextElement(); if (!$this->parseRequiredType('String', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_STRING); } $el->context = $this->lastParser->element; $foundSomething = $foundContext = true; } // Check if we have a comment if ($cursor->match('comment')) { if ($foundComment) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_COMMENT_DUPLICATE); } $this->findNextElement(); if (!$this->parseRequiredType('String', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_STRING); } $el->comment = $this->lastParser->element; $foundSomething = $foundComment = true; } // Check the variables. if ($cursor->match('vars')) { do { // save the cursor so that we can restore it to retry a different sequence $saveCursor = clone $cursor; // try to parse string => expression if ($elements = $this->parseSequence(array(array('type' => 'String'), array('type' => 'Character', 'args' => '=>'), array('type' => 'Expression')))) { $currentKeys[$elementNr] = $elements[0]; $currentArray[$elementNr] = $elements[1]; $elementNr++; continue; } // restore the cursor if not found $this->currentCursor = $saveCursor; $cursor = $saveCursor; // try to parse integer => expression if ($elements = $this->parseSequence(array(array('type' => 'Integer'), array('type' => 'Character', 'args' => '=>'), array('type' => 'Expression')))) { $currentKeys[$elementNr] = $elements[0]; $currentArray[$elementNr] = $elements[1]; $elementNr++; continue; } // restore the cursor if not found $this->currentCursor = $saveCursor; $cursor = $saveCursor; if (!$this->parseRequiredType('Expression', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, "Expecting a valid variable definition (String => Expression; Integer => Expression; or Expression)."); } $expression = $this->lastParser->rootOperator; unset($currentKeys[$elementNr]); $currentArray[$elementNr] = $expression; $elementNr++; } while ($cursor->match(',')); $array = new ezcTemplateLiteralArrayTstNode($this->parser->source, $this->startCursor, $cursor); $array->keys = $currentKeys; $array->value = $currentArray; $el->variables = $array; $foundSomething = true; } } while ($foundSomething); if (!$this->parentParser->atEnd($cursor, null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } $cursor->advance(); $this->appendElement($el); return true; }
/** * Parses the block by using sub parser, the conditions are: * - The block contains {*...*} in which case ezcTemplateDocCommentSourceToTstParser is * used. * - The block contains a generic expression in which case * ezcTemplateExpressionBlockSourceToTstParser is used. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { // Check for doc comments which look like {*...*} if (!$cursor->atEnd() && $cursor->current() == '*') { // got a doc comment block if (!$this->parseRequiredType('DocComment', $this->startCursor)) { throw new ezcTemplateParserException($this->parser->source, $cursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CLOSING_BLOCK_COMMENT); } return true; } // $cursor object in $block will be updated as the parser continues $this->block = new ezcTemplateBlockTstNode($this->parser->source, $this->startCursor, $cursor); $this->findNextElement(); // Test for and ending control structure. if (!$cursor->atEnd() && $cursor->current() == '/') { // got a closing block marker $this->block->isClosingBlock = true; $closingCursor = clone $cursor; $this->block->closingCursor = $closingCursor; $cursor->advance(1); $this->findNextElement(); // Check for internal blocks which are known to not support closing markers. // foreach|while|if|switch|case|default|delimiter|literal|dynamic|cache_template $matches = $cursor->pregMatchComplete("#^(tr|tr_context|elseif|else|include|return|break|continue|skip|increment|decrement|reset|once|var|use|cycle|ldelim|rdelim)(?:[^a-zA-Z0-9_])#"); if ($matches !== false) { throw new ezcTemplateParserException($this->parser->source, $this->block->closingCursor, $this->block->closingCursor, ezcTemplateSourceToTstErrorMessages::MSG_CLOSING_BLOCK_NOW_ALLOWED); } } // Try to parse a control structure $controlStructureParser = new ezcTemplateControlStructureSourceToTstParser($this->parser, $this, null); $controlStructureParser->block = $this->block; if ($this->parseOptionalType($controlStructureParser, null, false)) { if ($this->lastParser->status == self::PARSE_PARTIAL_SUCCESS) { return false; } $this->mergeElements($this->lastParser); return true; } // Try to parse a literal block if ($this->parseOptionalType('LiteralBlock', $this->startCursor)) { return true; } // Try to parse a declaration block if ($this->parseOptionalType('DeclarationBlock', $this->startCursor)) { return true; } // Try to parse as an expression, if this fails the normal block parser // is tried. if ($this->parseOptionalType('ExpressionBlock', $this->startCursor)) { if (!$this->currentCursor->match('}')) { if ($this->currentCursor->match('[', false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_UNEXPECTED_SQUARE_BRACKET_OPEN); } throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } return true; } if ($cursor->match('}')) { // Empty block found, this is allowed but the returned block // will be ignored when compiling $this->elements[] = $this->lastParser->block; return true; } // Parse the {ldelim} and {rdelim} $matches = $this->currentCursor->pregMatchComplete("#^(ldelim|rdelim)(?:[^a-zA-Z0-9_])#"); $name = $matches[1][0]; $ldelim = $name == 'ldelim' ? true : false; $rdelim = $name == 'rdelim' ? true : false; if ($ldelim || $rdelim) { $this->currentCursor->advance(strlen($name)); $this->findNextElement(); if (!$this->currentCursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } $text = new ezcTemplateTextBlockTstNode($this->parser->source, $this->startCursor, $this->endCursor); $text->text = $ldelim ? "{" : "}"; $this->appendElement($text); return true; } // Parse the cache blocks. $cacheParser = new ezcTemplateCacheSourceToTstParser($this->parser, $this, null); $cacheParser->block = $this->block; if ($this->parseOptionalType($cacheParser, null)) { return true; } // Try to parse custom blocks, these are pluggable and follows a generic syntax. $customBlockParser = new ezcTemplateCustomBlockSourceToTstParser($this->parser, $this, null); $customBlockParser->block = $this->block; if ($this->parseOptionalType($customBlockParser, null)) { return true; } $matches = $cursor->pregMatchComplete("#^([a-zA-Z_][a-zA-Z0-9_-]*)(?:[^a-zA-Z])#i"); throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, sprintf(ezcTemplateSourceToTstErrorMessages::MSG_UNKNOWN_BLOCK, $matches[1][0])); }
/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { $rawBlock = false; if ($cursor->match("raw")) { $rawBlock = true; $this->findNextElement(); } // $cursor will be update as the parser continues if ($this->startBracket == '(') { // This is a parenthesis so we use a different node type $this->block = new ezcTemplateParenthesisTstNode($this->parser->source, $this->startCursor, $cursor); $this->block->startBracket = $this->startBracket; $this->block->endBracket = $this->endBracket; } else { $this->block = new ezcTemplateOutputBlockTstNode($this->parser->source, $this->startCursor, $cursor); $this->block->isRaw = $rawBlock; $this->block->startBracket = $this->startBracket; $this->block->endBracket = $this->endBracket; } // skip whitespace and comments if (!$this->findNextElement()) { return false; } $allowIdentifier = false; // Check for expression, the parser will call atEnd() of this class to // check for end of the expression. $expressionParser = new ezcTemplateExpressionSourceToTstParser($this->parser, $this, null); $expressionParser->setAllCursors($cursor); $expressionParser->startCursor = clone $cursor; $expressionParser->allowEmptyExpressions = true; if (!$this->parseRequiredType($expressionParser, $this->startCursor, false)) { return false; } $this->findNextElement(); $rootOperator = $this->lastParser->currentOperator; if ($rootOperator instanceof ezcTemplateOperatorTstNode) { $rootOperator = $rootOperator->getRoot(); } // If there is no root operator the block is empty, change the block type. if ($rootOperator === null) { $this->block = new ezcTemplateEmptyBlockTstNode($this->parser->source, clone $this->startCursor, $cursor); $this->appendElement($this->block); return true; } // Change the block type if the top-most operator is a modifiying operator. if ($rootOperator instanceof ezcTemplateModifyingOperatorTstNode) { if ($rawBlock) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_ASSIGNMENT_NOT_ALLOWED); } // @todo if the parser block is a parenthesis it is not allowed to have modifying nodes $oldBlock = $this->block; $this->block = new ezcTemplateModifyingBlockTstNode($this->parser->source, clone $this->startCursor, $cursor); $this->block->startBracket = $this->startBracket; $this->block->endBracket = $this->endBracket; $this->block->children = $oldBlock->children; } $this->block->expressionRoot = $rootOperator; $this->block->children = array($rootOperator); $this->appendElement($this->block); return true; }
/** * Parse assignment operator * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseAssignmentOperator($cursor) { if ($cursor->match("=")) { $function = "ezcTemplateAssignmentOperatorTstNode"; $operator = new $function($this->parser->source, clone $this->lastCursor, $cursor); $this->checkForValidOperator($this->currentOperator, $operator, $cursor); $this->currentOperator = $this->parser->handleOperatorPrecedence($this->currentOperator, $operator); return true; } return false; }
/** * Parse a parameter * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseParameter($cursor) { // Without this, the expression parser keeps on reading. if ($cursor->match(')', false)) { return false; } $this->readingParameter = true; $startCursor = clone $cursor; $namedParameter = $cursor->pregMatch("#^[a-zA-Z_][a-zA-Z0-9_]*#"); if ($namedParameter !== false) { $this->findNextElement(); if (!$cursor->match("=")) { $namedParameter = false; } } if ($namedParameter === false) { $cursor->copy($startCursor); } // Check for expression, the parser will call self::atEnd() to check for end of expression. $expressionStartCursor = clone $cursor; $expressionParser = new ezcTemplateExpressionSourceToTstParser($this->parser, $this, null); $expressionParser->allowIdentifier = true; if (!$this->parseRequiredType($expressionParser) || $this->lastParser->currentOperator === null) { return false; } $rootOperator = $this->lastParser->currentOperator; if ($rootOperator instanceof ezcTemplateOperatorTstNode) { $rootOperator = $rootOperator->getRoot(); } if ($rootOperator instanceof ezcTemplateModifyingOperatorTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, sprintf(ezcTemplateSourceToTstErrorMessages::MSG_PARAMETER_CANNOT_BE_MODIFYING_BLOCK, $this->parameterCount)); } if ($namedParameter !== false) { if (isset($this->functionCall->parameters[$namedParameter])) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, sprintf(ezcTemplateSourceToTstErrorMessages::MSG_NAMED_PARAMETER_ALREADY_ASSIGNED, $namedParameter)); } $this->functionCall->parameters[$namedParameter] = $rootOperator; } else { $this->functionCall->appendParameter($rootOperator); } $this->readingParameter = false; return true; }
/** * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { $name = $this->block->name; // handle closing block if ($this->block->isClosingBlock) { // skip whitespace and comments $this->findNextElement(); if (!$cursor->match('}')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } if ($name == 'switch') { $sw = new ezcTemplateSwitchTstNode($this->parser->source, $this->startCursor, $cursor); } else { // Tricky: Skip the spaces and new lines. Next element should be an case, or default. // $this->findNextElement(); $sw = new ezcTemplateCaseTstNode($this->parser->source, $this->startCursor, $cursor); $sw->name = $name; // Set the name to either 'case' or 'default'. } // $el->name = 'switch'; $sw->isClosingBlock = true; $this->appendElement($sw); return true; } if ($name == 'switch') { $this->findNextElement(); if (!$this->parseRequiredType('Expression', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_EXPRESSION); } if ($this->lastParser->rootOperator instanceof ezcTemplateModifyingOperatorTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_MODIFYING_EXPRESSION_NOT_ALLOWED); } $this->findNextElement(); if (!$cursor->match('}')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } // Tricky: Skip the spaces and new lines. Next element should be an case, or default. // $this->findNextElement(); $sw = new ezcTemplateSwitchTstNode($this->parser->source, $this->startCursor, $cursor); $sw->condition = $this->lastParser->rootOperator; $this->appendElement($sw); return true; } elseif ($name == 'case') { $case = new ezcTemplateCaseTstNode($this->parser->source, $this->startCursor, $cursor); $case->name = $name; // Set the name to 'case' do { $this->findNextElement(); if (!$this->parseRequiredType('Literal', null, false)) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_LITERAL); } $case->conditions[] = $this->lastParser->element; $this->findNextElement(); } while ($cursor->match(',')); if (!$cursor->match('}')) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } // Tricky: Skip the spaces and new lines. Next element should be an case, or default. $this->findNextElement(); $this->appendElement($case); return true; } elseif ($name == 'default') { $case = new ezcTemplateCaseTstNode($this->parser->source, $this->startCursor, $cursor); $case->name = $name; // Set the name to 'default' $case->conditions = null; $this->findNextElement(); if (!$cursor->match('}')) { throw new ezcTemplateSourceToTstParserException($this, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } // Tricky: Skip the spaces and new lines. Next element should be an case, or default. $this->findNextElement(); $this->appendElement($case); return true; } }
/** * Parses the literal by using the ezcTemplateLiteralParser class. * * @param ezcTemplateCursor $cursor * @return bool */ protected function parseCurrent(ezcTemplateCursor $cursor) { // $cursor will be update as the parser continues $this->block = new ezcTemplateLiteralBlockTstNode($this->parser->source, clone $this->startCursor, $cursor); // skip whitespace and comments if (!$this->findNextElement()) { return false; } $hasClosingMarker = $cursor->current() == '/'; if ($hasClosingMarker) { $closingCursor = clone $cursor; $cursor->advance(); $this->findNextElement(); } $matches = $cursor->pregMatchComplete("#^(literal)(?:[^a-zA-Z0-9_])#"); if ($matches === false) { return false; } $cursor->advance(strlen($matches[1][0])); // skip whitespace and comments if (!$this->findNextElement()) { return false; } // Assume end of first {literal} block if (!$cursor->match("}")) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $cursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE); } if ($hasClosingMarker) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $cursor, "Found closing block {/literal} without an opening block."); } $literalTextCursor = clone $cursor; // Start searching for ending literal block. while (!$cursor->atEnd()) { // Find the next block $tagPos = $cursor->findPosition("{"); if ($tagPos === false) { return false; } $tagCursor = clone $cursor; $tagCursor->gotoPosition($tagPos - 1); if ($tagCursor->current() == "\\") { // This means the tag is escaped and should be treated as text. $cursor->copy($tagCursor); $cursor->advance(2); unset($tagCursor); continue; } // Reached a block {...} $cursor->gotoPosition($tagPos); $literalTextEndCursor = clone $cursor; $cursor->advance(); $continue = false; while (!$cursor->atEnd()) { // skip whitespace and comments if (!$this->findNextElement()) { return false; } // Check for end, if not continue search if (!$cursor->match('/literal')) { $continue = true; break; } // skip whitespace and comments if (!$this->findNextElement()) { return false; } if ($cursor->current() == '}') { $this->block->textStartCursor = $literalTextCursor; $this->block->textEndCursor = $literalTextEndCursor; $cursor->advance(); $this->block->endCursor = clone $cursor; // Make sure the text is extracted now that the cursor are correct $this->block->storeText(); $this->appendElement($this->block); return true; } } if ($continue) { continue; } } return false; }