/**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $result = array();
     while ($token = $stream->next()) {
         $result[] = $token;
     }
     // Looking for `$` pattern
     if ($result[count($result) - 1] instanceof TokenInterface && $result[count($result) - 1]->is('T_DOLLAR') && count($result) > 1) {
         $result[count($result) - 2] = new EndNode($this->parser->parseStream(new Stream(array($result[count($result) - 2])))->input());
         array_pop($result);
     }
     unset($stream);
     return new Stream($result);
 }
 /**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @throws ParserException
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $blocksFound = 0;
     $stack = array();
     $result = array();
     while ($token = $stream->next()) {
         if (!$token instanceof TokenInterface) {
             if ($blocksFound === 0) {
                 $result[] = $token;
             } else {
                 $stack[] = $token;
             }
             continue;
         }
         // Looking for `[` pattern
         if ($token->is('T_LEFT_BRACKET')) {
             ++$blocksFound;
             if ($blocksFound > 1) {
                 // We matched a nested parenthesis so we ignore it
                 $stack[] = $token;
             }
         } elseif ($blocksFound > 0 && $token->is('T_RIGHT_BRACKET')) {
             if ($blocksFound === 1) {
                 $result[] = new BlockNode($this->parser->parseStream(new Stream($stack), 'BracketBlockParserPass', array('BracketBlockParserPass'))->input());
                 $stack = array();
             } else {
                 $stack[] = $token;
             }
             --$blocksFound;
         } elseif ($blocksFound > 0) {
             $stack[] = $token;
         } elseif ($blocksFound === 0 && $token->is('T_RIGHT_BRACKET')) {
             throw new ParserException('Bracket block not opened');
         } else {
             $result[] = $token;
         }
     }
     if ($blocksFound > 0) {
         throw new ParserException('Bracket block not closed');
     }
     unset($stream);
     return new Stream($result);
 }
 /**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @throws ParserException
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $commentFound = false;
     $stack = array();
     $result = array();
     while ($token = $stream->next()) {
         if ($stream->cursor() < 2 || !$token instanceof TokenInterface) {
             $result[] = $token;
             continue;
         }
         // Looking for `(?#` pattern
         if ($token->is('T_POUND') && $stream->readAt(-1)->is('T_QUESTION') && $stream->readAt(-2)->is('T_LEFT_PARENTHESIS') && !$commentFound) {
             $commentFound = true;
             // We remove (? from result
             array_pop($result);
             array_pop($result);
         } elseif ($commentFound && $token->is('T_RIGHT_PARENTHESIS')) {
             // $stack contains our comment but we don't keep it
             $commentFound = false;
             $stack = array();
         } elseif ($commentFound) {
             $stack[] = $token;
         } else {
             $result[] = $token;
         }
     }
     if ($commentFound) {
         throw new ParserException('Comment not closed');
     }
     unset($stream);
     return new Stream($result);
 }
 /**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @throws ParserException
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $result = array();
     while ($token = $stream->next()) {
         if (!$token instanceof TokenInterface) {
             $result[] = $token;
             continue;
         }
         // Looking for `*-*` pattern
         if ($token->is('T_PIPE')) {
             if ($stream->cursor() < 1 || !$stream->hasNext()) {
                 throw new ParserException('Alternative must have a previous and a next token');
             }
             if ($result[count($result) - 1] instanceof AlternativeNode) {
                 if ($stream->readAt(1) instanceof TokenInterface) {
                     $result[count($result) - 1]->appendChild(new TokenNode($stream->next()));
                 } else {
                     $result[count($result) - 1]->appendChild($stream->next());
                 }
                 continue;
             }
             // Remove previous
             array_pop($result);
             $previous = $stream->readAt(-1);
             if ($previous instanceof TokenInterface) {
                 $previous = new TokenNode($previous);
             }
             $next = $stream->next();
             if ($next instanceof TokenInterface) {
                 $next = new TokenNode($next);
             }
             $result[] = new AlternativeNode(array($previous, $next));
         } else {
             $result[] = $token;
         }
     }
     unset($stream);
     return new Stream($result);
 }
예제 #5
0
 /**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $result = array();
     while ($token = $stream->next()) {
         if (!$token instanceof TokenInterface) {
             $result[] = $token;
             continue;
         }
         // Looking for `^` pattern
         if ($token->is('T_HAT') && $stream->cursor() === 0) {
             if ($parentPass === 'BracketBlockParserPass') {
                 $childNodes = $stream->input();
                 array_shift($childNodes);
                 // Remove ^
                 return new Stream(array(new ExclusionNode($this->parser->parseStream(new Stream($childNodes), 'BracketBlockParserPass', array('BracketBlockParserPass'))->input())));
             }
             $result[] = new BeginNode($this->parser->parseStream(new Stream(array($stream->next())))->input());
         } else {
             $result[] = $token;
         }
     }
     unset($stream);
     return new Stream($result);
 }
 /**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @throws ParserException
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $blockFound = false;
     $stack = array(0 => array(), 1 => array());
     $step = 0;
     $result = array();
     while ($token = $stream->next()) {
         if (!$token instanceof TokenInterface) {
             $result[] = $token;
             continue;
         }
         // Looking for `*` pattern
         if ($token->is('T_MULTIPLY')) {
             if ($stream->cursor() < 1) {
                 throw new ParserException('A repetition pattern must follow a token');
             }
             // We remove the last token
             array_pop($result);
             $child = $stream->readAt(-1);
             if ($child instanceof TokenInterface) {
                 $child = new TokenNode($child);
             }
             $result[] = new RepetitionNode(0, null, array($child));
             // We reinject the current node into the stream to handle case like +? and so on...
             $stream->replace($stream->cursor(), $result[count($result) - 1]);
         } elseif ($token->is('T_PLUS')) {
             // Looking for `+` pattern
             if ($stream->cursor() < 1) {
                 throw new ParserException('A repetition pattern must follow a token');
             }
             // We remove the last token
             array_pop($result);
             $child = $stream->readAt(-1);
             if ($child instanceof TokenInterface) {
                 $child = new TokenNode($child);
             }
             $result[] = new RepetitionNode(1, null, array($child));
             // We reinject the current node into the stream to handle case like +? and so on...
             $stream->replace($stream->cursor(), $result[count($result) - 1]);
         } elseif ($token->is('T_QUESTION')) {
             // Looking for `?` pattern
             if ($stream->cursor() < 1) {
                 throw new ParserException('A repetition pattern must follow a token');
             }
             // We remove the last token
             array_pop($result);
             $child = $stream->readAt(-1);
             if ($child instanceof TokenInterface) {
                 $child = new TokenNode($child);
             }
             $result[] = new RepetitionNode(0, 1, array($child));
             // We reinject the current node into the stream to handle case like +? and so on...
             $stream->replace($stream->cursor(), $result[count($result) - 1]);
         } elseif ($token->is('T_LEFT_BRACE')) {
             if ($stream->cursor() < 1) {
                 throw new ParserException('A repetition pattern must follow a token');
             }
             $blockFound = true;
         } elseif ($blockFound && $token->is('T_INTEGER')) {
             $stack[$step][] = $token;
         } elseif ($blockFound && $step === 0 && $token->is('T_COMMA')) {
             ++$step;
         } elseif ($blockFound && $token->is('T_RIGHT_BRACE')) {
             $blockFound = false;
             array_pop($result);
             $min = (int) implode('', array_map(function ($t) {
                 return $t->getValue();
             }, $stack[0]));
             if (count($stack[1]) > 0) {
                 $max = (int) implode('', array_map(function ($t) {
                     return $t->getValue();
                 }, $stack[1]));
                 if ($max !== null && $min >= $max) {
                     throw new ParserException('Min must be greater than max in a repetition pattern');
                 }
                 $offset = 3;
                 // +3 because of {,}
             } else {
                 $max = $min;
                 $offset = 2;
                 // +3 because of {}
             }
             $child = $stream->readAt(-(count($stack[0]) + count($stack[1]) + $offset));
             if ($child instanceof TokenInterface) {
                 $child = new TokenNode($child);
             }
             $result[] = new RepetitionNode($min, $max, array($child));
             $stack = array(0 => array(), 1 => array());
             $step = 0;
             // We reinject the current node into the stream to handle case like +? and so on...
             $stream->replace($stream->cursor(), $result[count($result) - 1]);
         } elseif ($blockFound) {
             throw new ParserException('Invalid token in repetition pattern');
         } else {
             $result[] = $token;
         }
     }
     unset($stream);
     return new Stream($result);
 }
 /**
  * @param StreamInterface $stream
  * @param string|null     $parentPass
  *
  * @return Stream
  */
 public function parseStream(StreamInterface $stream, $parentPass = null)
 {
     $result = array();
     $used = array();
     while ($token = $stream->next()) {
         if ($stream->cursor() < 1 || !$token instanceof TokenInterface) {
             $result[] = $token;
             continue;
         }
         // Looking for `*-*` pattern
         if ($token->is('T_MINUS') && $stream->readAt(-1) instanceof TokenInterface && $stream->readAt(1) instanceof TokenInterface && !in_array($stream->cursor() - 1, $used) && $this->isPreviousNextTokenValid($stream->readAt(-1), $stream->readAt(1), $parentPass)) {
             // Remove *
             array_pop($result);
             $used[] = $stream->cursor();
             $used[] = $stream->cursor() - 1;
             $used[] = $stream->cursor() + 1;
             $result[] = new CharacterClassNode(new TokenNode($stream->readAt(-1)), new TokenNode($stream->readAt(1)));
             $stream->next();
         } else {
             $result[] = $token;
         }
     }
     unset($stream);
     return new Stream($result);
 }