/**
  * Parses the comment by looking for the end marker \n.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     $cutOff = false;
     if (!$cursor->atEnd()) {
         $cursor->advance(2);
         $matches = $cursor->pregMatchComplete("#^([^}\r\n]*)(?:(?:})|(\r|\r\n|\n))#");
         if ($matches) {
             // reached end of comment
             $cutOff = false;
             if (isset($matches[2])) {
                 $cursor->advance($matches[2][1] + strlen($matches[2][0]));
                 // Do not include the newline itself in the comment.
                 $cutOff = -1;
             } else {
                 $cursor->advance($matches[1][1] + strlen($matches[1][0]));
             }
         } else {
             $cursor->gotoEnd();
         }
         $commentBlock = new ezcTemplateEolCommentTstNode($this->parser->source, $this->startCursor, clone $cursor);
         if ($cutOff) {
             $commentBlock->commentText = substr($commentBlock->text(), 2, $cutOff);
         } else {
             $commentBlock->commentText = substr($commentBlock->text(), 2);
         }
         $this->appendElement($commentBlock);
         return true;
     }
     return false;
 }
 /**
  * Parses the comment by looking for the end marker * + }.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     $cursor->advance();
     if ($cursor->atEnd()) {
         return false;
     }
     $checkInlineComment = false;
     // Check for a slash after the asterix, this typically means a typo for an inline comment
     // Better give an error for this to warn the user.
     if ($cursor->current() == '/') {
         $checkInlineComment = true;
     }
     $endPosition = $cursor->findPosition('*}');
     if ($endPosition === false) {
         return false;
     }
     // If we found an end for an inline comment we need to check if there
     // is an end for an inline comment
     if ($checkInlineComment) {
         $commentCursor = $cursor->cursorAt($cursor->position, $endPosition);
         $commentCursor->advance();
         $inlineCommentPosition = $commentCursor->findPosition('*/');
         // We found the end of the inline comment, this is most likely a user error
         if ($inlineCommentPosition !== false) {
             $cursor->gotoPosition($inlineCommentPosition);
             return false;
         }
     }
     // reached end of comment
     $cursor->gotoPosition($endPosition + 2);
     $commentBlock = new ezcTemplateDocCommentTstNode($this->parser->source, clone $this->startCursor, clone $cursor);
     $commentBlock->commentText = substr($commentBlock->text(), 2, -2);
     $this->appendElement($commentBlock);
     return true;
 }
Exemple #3
0
 /**
  * Parses the boolean types by looking for either 'true' or 'false'.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     if (!$cursor->atEnd()) {
         // @todo This should check that there is no alphabetical characters
         //       after the true|false.
         $matches = $cursor->pregMatchComplete("#^(true|false)(?:\\W)#i");
         if ($matches === false) {
             return false;
         }
         $name = $matches[1][0];
         $lower = strtolower($name);
         if ($name !== $lower) {
             $this->findNonLowercase();
             throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_BOOLEAN_NOT_LOWERCASE);
         }
         $cursor->advance(strlen($name));
         $bool = new ezcTemplateLiteralTstNode($this->parser->source, $this->startCursor, $cursor);
         $bool->value = $name == 'true';
         $this->value = $bool->value;
         $this->element = $bool;
         $this->appendElement($bool);
         return true;
     }
     return false;
 }
Exemple #4
0
 /**
  * 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;
 }
Exemple #5
0
 /**
  * Parses the float types by looking for float expression.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     if (!$cursor->atEnd()) {
         $matches = $cursor->pregMatch("#^(?:[0-9]+(([eE][+-]?[0-9]+)|((\\.[0-9]+)([eE][+-]?[0-9]+)?)))#");
         if ($matches !== false) {
             $float = new ezcTemplateLiteralTstNode($this->parser->source, $this->startCursor, $cursor);
             $float->value = (double) $matches;
             $this->value = $float->value;
             $this->element = $float;
             $this->appendElement($float);
             return true;
         }
     }
     return false;
 }
 /**
  * Parses the identifier types by looking for allowed characters.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     if (!$cursor->atEnd()) {
         $matches = $cursor->pregMatch("#^[a-zA-Z_][a-zA-Z0-9_]*#");
         if ($matches !== false) {
             $identifier = new ezcTemplateIdentifierTstNode($this->parser->source, $this->startCursor, $cursor);
             $identifier->value = (string) $matches;
             $this->identifierName = $identifier->value;
             $this->element = $identifier;
             $this->appendElement($identifier);
             return true;
         }
     }
     return false;
 }
Exemple #7
0
 /**
  * Parses the integer types by looking for numerical characters.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     if (!$cursor->atEnd()) {
         $matches = $cursor->pregMatch("#^-?[0-9]+#");
         if ($matches !== false) {
             $integer = new ezcTemplateLiteralTstNode($this->parser->source, $this->startCursor, $cursor);
             $integer->value = (int) $matches;
             $this->value = $integer->value;
             $this->element = $integer;
             $this->appendElement($integer);
             return true;
         }
     }
     return false;
 }
Exemple #8
0
 /**
  * Parses the code by looking for start of expression blocks and then
  * passing control to the block parser (ezcTemplateBlockSourceToTstParser). The
  * text which is not covered by the block parser will be added as
  * text elements.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     $this->program = new ezcTemplateProgramTstNode($this->parser->source, $this->startCursor, $cursor);
     $this->lastBlock = $this->program;
     while (!$cursor->atEnd()) {
         // Find the first block
         $bracePosition = $cursor->findPosition("{", true);
         if ($bracePosition === false) {
             $cursor->gotoEnd();
             // This will cause handleSuccessfulResult() to be called
             return true;
         }
         // Reached a block {...}
         $cursor->gotoPosition($bracePosition);
         $blockCursor = clone $cursor;
         $cursor->advance(1);
         if ($this->lastCursor->length($blockCursor) > 0) {
             $textElement = new ezcTemplateTextBlockTstNode($this->parser->source, clone $this->lastCursor, clone $blockCursor);
             $this->handleElements(array($textElement));
             unset($textElement);
         }
         $this->startCursor->copy($blockCursor);
         $this->lastCursor->copy($cursor);
         if (!$this->parseRequiredType('Block', $this->startCursor, false)) {
             return false;
         }
         $this->startCursor->copy($cursor);
         $elements = $this->lastParser->elements;
         // Sanity checking to make sure element list does not contain duplicates,
         // this avoids having infinite recursions
         $count = count($elements);
         if ($count > 0) {
             $offset = 0;
             while ($offset < $count) {
                 $element = $elements[$offset];
                 for ($i = $offset + 1; $i < $count; ++$i) {
                     if ($element === $elements[$i]) {
                         throw new ezcTemplateInternalException("Received element list with duplicate objects from parser " . get_class($this->lastParser));
                     }
                 }
                 ++$offset;
             }
         }
         $this->handleElements($elements);
     }
     // This will cause handleSuccessfulResult() to be called
     return true;
 }
Exemple #9
0
 /**
  * Parses the comment by looking for the end marker * + /.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     if (!$cursor->atEnd()) {
         $cursor->advance(2);
         $tagPos = $cursor->findPosition('*/');
         if ($tagPos !== false) {
             // reached end of comment
             $cursor->gotoPosition($tagPos + 2);
             $commentBlock = new ezcTemplateBlockCommentTstNode($this->parser->source, $this->startCursor, clone $cursor);
             $commentBlock->commentText = substr($commentBlock->text(), 2, -2);
             $this->appendElement($commentBlock);
             return true;
         }
     }
     return false;
 }
Exemple #10
0
 /**
  * Parses the types by utilizing:
  * - ezcTemplateFloatSourceToTstParser for float types.
  * - ezcTemplateIntegerSourceToTstParser for integer types.
  * - ezcTemplateStringSourceToTstParser for string types.
  * - ezcTemplateBoolSourceToTstParser for boolean types.
  * - ezcTemplateArraySourceToTstParser for array types.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     $failedParser = null;
     if (!$cursor->atEnd()) {
         // Try parsing the various type types until one is found
         $failedCursor = clone $cursor;
         $types = array('Float', 'Integer', 'String', 'Bool', 'Array', 'Null');
         foreach ($types as $type) {
             if ($this->parseOptionalType($type)) {
                 $this->lastCursor->copy($this->startCursor);
                 $this->value = $this->lastParser->value;
                 $this->element = $this->lastParser->element;
                 return true;
             }
         }
     }
     return false;
 }
Exemple #11
0
 /**
  * Parses the string types by looking for single or double quotes to start
  * the string.
  *
  * @param ezcTemplateCursor $cursor
  * @return bool
  */
 protected function parseCurrent(ezcTemplateCursor $cursor)
 {
     if (!$cursor->atEnd()) {
         $char = $cursor->current();
         if ($char == '"' || $char == "'") {
             $string = new ezcTemplateLiteralTstNode($this->parser->source, $this->startCursor, $cursor);
             $string->quoteType = $char == "'" ? ezcTemplateLiteralTstNode::SINGLE_QUOTE : ezcTemplateLiteralTstNode::DOUBLE_QUOTE;
             $cursor->advance();
             $nextChar = $cursor->current();
             if ($nextChar === $char) {
                 // We know it is an empty string, no need to extract
                 $str = "";
                 $string->value = $str;
                 $this->value = $string->value;
                 $this->element = $string;
                 $this->appendElement($string);
                 $cursor->advance();
                 return true;
             } else {
                 // Match:
                 // ([^{$char}\\\\]|\A)   : Matches non quote ('"', "'"), non backslash (\), or does match the begin of the statement.
                 // (\\\\(\\\\|{$char}))* : Eat double slashes \\ and slash quotes: \' or \".
                 $matches = $cursor->pregMatchComplete("#(?:([^{$char}\\\\]|\\A)(\\\\(\\\\|{$char}))*){$char}#");
                 if ($matches === false) {
                     return false;
                 }
                 $cursor->advance($matches[0][1] + strlen($matches[0][0]));
                 $str = (string) $this->startCursor->subString($cursor->position);
                 $str = substr($str, 1, -1);
                 $string->value = $str;
                 $this->value = $string->value;
                 $this->element = $string;
                 $this->appendElement($string);
                 return true;
             }
         }
     }
     return false;
 }
Exemple #12
0
 /**
  * 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;
 }
Exemple #13
0
 /**
  * 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]));
 }
Exemple #14
0
 /**
  * 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;
 }