📄 parser.php
字号:
<?php/** * Twig::Parser * ~~~~~~~~~~~~ * * This module implements the Twig parser. * * :copyright: 2008 by Armin Ronacher. * :license: BSD. */function twig_parse($source, $filename=NULL){ $stream = twig_tokenize($source, $filename); $parser = new Twig_Parser($stream); return $parser->parse();}class Twig_Parser{ public $stream; public $blocks; public $extends; public $current_block; private $handlers; public function __construct($stream) { $this->stream = $stream; $this->extends = NULL; $this->blocks = array(); $this->current_block = NULL; $this->handlers = array( 'for' => array($this, 'parseForLoop'), 'if' => array($this, 'parseIfCondition'), 'extends' => array($this, 'parseExtends'), 'include' => array($this, 'parseInclude'), 'block' => array($this, 'parseBlock'), 'super' => array($this, 'parseSuper'), # Chyrp specific extensions 'url' => array($this, 'parseURL'), 'admin' => array($this, 'parseAdminURL'), 'paginate' => array($this, 'parsePaginate') ); } public function parseForLoop($token) { $lineno = $token->lineno; list($is_multitarget, $item) = $this->parseAssignmentExpression(); $this->stream->expect('in'); $seq = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->subparse(array($this, 'decideForFork')); if ($this->stream->next()->value == 'else') { $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $else = $this->subparse(array($this, 'decideForEnd'), true); } else $else = NULL; $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_ForLoop($is_multitarget, $item, $seq, $body, $else, $lineno); } public function parsePaginate($token) { $lineno = $token->lineno; list($is_multitarget, $item) = $this->parseAssignmentExpression(); $this->stream->expect('in'); $per_page = $this->parseExpression(); $loop = $this->parseExpression(); $this->stream->expect('as'); $as = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->subparse(array($this, 'decidePaginateFork')); if ($this->stream->next()->value == 'else') { $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $else = $this->subparse(array($this, 'decidePaginateEnd'), true); } else $else = NULL; $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_PaginateLoop($is_multitarget, $item, $per_page, $loop, $as, $body, $else, $lineno); } public function decideForFork($token) { return $token->test(array('else', 'endfor')); } public function decideForEnd($token) { return $token->test('endfor'); } public function decidePaginateFork($token) { return $token->test(array('else', 'endpaginate')); } public function decidePaginateEnd($token) { return $token->test('endpaginate'); } public function parseIfCondition($token) { $lineno = $token->lineno; $expr = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->subparse(array($this, 'decideIfFork')); $tests = array(array($expr, $body)); $else = NULL; $end = false; while (!$end) switch ($this->stream->next()->value) { case 'else': $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $else = $this->subparse(array($this, 'decideIfEnd')); break; case 'elseif': $expr = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->subparse(array($this, 'decideIfFork')); $tests[] = array($expr, $body); break; case 'endif': $end = true; break; } $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_IfCondition($tests, $else, $lineno); } public function decideIfFork($token) { return $token->test(array('elseif', 'else', 'endif')); } public function decideIfEnd($token) { return $token->test(array('endif')); } public function parseBlock($token) { $lineno = $token->lineno; $name = $this->stream->expect(Twig_Token::NAME_TYPE)->value; if (isset($this->blocks[$name])) throw new Twig_SyntaxError("block '$name' defined twice.", $lineno); $this->current_block = $name; $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->subparse(array($this, 'decideBlockEnd'), true); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); $block = new Twig_Block($name, $body, $lineno); $this->blocks[$name] = $block; $this->current_block = NULL; return new Twig_BlockReference($name, $lineno); } public function decideBlockEnd($token) { return $token->test('endblock'); } public function parseExtends($token) { $lineno = $token->lineno; if (!is_null($this->extends)) throw new Twig_SyntaxError('multiple extend tags', $lineno); $this->extends = $this->stream->expect(Twig_Token::STRING_TYPE)->value; $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return NULL; } public function parseInclude($token) { $expr = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_Include($expr, $token->lineno); } public function parseSuper($token) { if (is_null($this->current_block)) throw new Twig_SyntaxError('super outside block', $token->lineno); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_Super($this->current_block, $token->lineno); } public function parseURL($token) { $expr = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_URL($expr, $token->lineno); } public function parseAdminURL($token) { $expr = $this->parseExpression(); $this->stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_AdminURL($expr, $token->lineno); } public function parseExpression() { return $this->parseConditionalExpression(); } public function parseConditionalExpression() { $lineno = $this->stream->current->lineno; $expr1 = $this->parseOrExpression(); while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '?')) { $this->stream->next(); $expr2 = $this->parseOrExpression(); $this->stream->expect(Twig_Token::OPERATOR_TYPE, ':'); $expr3 = $this->parseConditionalExpression(); $expr1 = new Twig_ConditionalExpression($expr1, $expr2, $expr3, $this->lineno); $lineno = $this->stream->current->lineno; } return $expr1; } public function parseOrExpression() { $lineno = $this->stream->current->lineno; $left = $this->parseAndExpression(); while ($this->stream->test('or')) { $this->stream->next(); $right = $this->parseAndExpression(); $left = new Twig_OrExpression($left, $right, $lineno); $lineno = $this->stream->current->lineno; } return $left; } public function parseAndExpression() { $lineno = $this->stream->current->lineno; $left = $this->parseCompareExpression(); while ($this->stream->test('and')) { $this->stream->next(); $right = $this->parseCompareExpression(); $left = new Twig_AndExpression($left, $right, $lineno); $lineno = $this->stream->current->lineno; } return $left; } public function parseCompareExpression() { static $operators = array('==', '!=', '<', '>', '>=', '<='); $lineno = $this->stream->current->lineno; $expr = $this->parseAddExpression(); $ops = array(); while ($this->stream->test(Twig_Token::OPERATOR_TYPE, $operators)) $ops[] = array($this->stream->next()->value, $this->parseAddExpression()); if (empty($ops)) return $expr; return new Twig_CompareExpression($expr, $ops, $lineno); } public function parseAddExpression() { $lineno = $this->stream->current->lineno; $left = $this->parseSubExpression(); while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '+')) { $this->stream->next(); $right = $this->parseSubExpression(); $left = new Twig_AddExpression($left, $right, $lineno); $lineno = $this->stream->current->lineno; } return $left; } public function parseSubExpression() { $lineno = $this->stream->current->lineno; $left = $this->parseConcatExpression(); while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '-')) { $this->stream->next(); $right = $this->parseConcatExpression(); $left = new Twig_SubExpression($left, $right, $lineno); $lineno = $this->stream->current->lineno; } return $left;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -