function ParserAbstract::doParse
Return value
Stmt[]|null
1 call to ParserAbstract::doParse()
- ParserAbstract::parse in vendor/
nikic/ php-parser/ lib/ PhpParser/ ParserAbstract.php - Parses PHP code into a node tree.
File
-
vendor/
nikic/ php-parser/ lib/ PhpParser/ ParserAbstract.php, line 220
Class
Namespace
PhpParserCode
protected function doParse() : ?array {
// We start off with no lookahead-token
$symbol = self::SYMBOL_NONE;
$tokenValue = null;
$this->tokenPos = -1;
// Keep stack of start and end attributes
$this->tokenStartStack = [];
$this->tokenEndStack = [
0,
];
// Start off in the initial state and keep a stack of previous states
$state = 0;
$stateStack = [
$state,
];
// Semantic value stack (contains values of tokens and semantic action results)
$this->semStack = [];
// Current position in the stack(s)
$stackPos = 0;
$this->errorState = 0;
for (;;) {
//$this->traceNewState($state, $symbol);
if ($this->actionBase[$state] === 0) {
$rule = $this->actionDefault[$state];
}
else {
if ($symbol === self::SYMBOL_NONE) {
do {
$token = $this->tokens[++$this->tokenPos];
$tokenId = $token->id;
} while (isset($this->dropTokens[$tokenId]));
// Map the lexer token id to the internally used symbols.
$tokenValue = $token->text;
if (!isset($this->phpTokenToSymbol[$tokenId])) {
throw new \RangeException(sprintf('The lexer returned an invalid token (id=%d, value=%s)', $tokenId, $tokenValue));
}
$symbol = $this->phpTokenToSymbol[$tokenId];
//$this->traceRead($symbol);
}
$idx = $this->actionBase[$state] + $symbol;
if (($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) && ($action = $this->action[$idx]) !== $this->defaultAction) {
/*
* >= numNonLeafStates: shift and reduce
* > 0: shift
* = 0: accept
* < 0: reduce
* = -YYUNEXPECTED: error
*/
if ($action > 0) {
/* shift */
//$this->traceShift($symbol);
++$stackPos;
$stateStack[$stackPos] = $state = $action;
$this->semStack[$stackPos] = $tokenValue;
$this->tokenStartStack[$stackPos] = $this->tokenPos;
$this->tokenEndStack[$stackPos] = $this->tokenPos;
$symbol = self::SYMBOL_NONE;
if ($this->errorState) {
--$this->errorState;
}
if ($action < $this->numNonLeafStates) {
continue;
}
/* $yyn >= numNonLeafStates means shift-and-reduce */
$rule = $action - $this->numNonLeafStates;
}
else {
$rule = -$action;
}
}
else {
$rule = $this->actionDefault[$state];
}
}
for (;;) {
if ($rule === 0) {
/* accept */
//$this->traceAccept();
return $this->semValue;
}
if ($rule !== $this->unexpectedTokenRule) {
/* reduce */
//$this->traceReduce($rule);
$ruleLength = $this->ruleToLength[$rule];
try {
$callback = $this->reduceCallbacks[$rule];
if ($callback !== null) {
$callback($this, $stackPos);
}
elseif ($ruleLength > 0) {
$this->semValue = $this->semStack[$stackPos - $ruleLength + 1];
}
} catch (Error $e) {
if (-1 === $e->getStartLine()) {
$e->setStartLine($this->tokens[$this->tokenPos]->line);
}
$this->emitError($e);
// Can't recover from this type of error
return null;
}
/* Goto - shift nonterminal */
$lastTokenEnd = $this->tokenEndStack[$stackPos];
$stackPos -= $ruleLength;
$nonTerminal = $this->ruleToNonTerminal[$rule];
$idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos];
if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) {
$state = $this->goto[$idx];
}
else {
$state = $this->gotoDefault[$nonTerminal];
}
++$stackPos;
$stateStack[$stackPos] = $state;
$this->semStack[$stackPos] = $this->semValue;
$this->tokenEndStack[$stackPos] = $lastTokenEnd;
if ($ruleLength === 0) {
// Empty productions use the start attributes of the lookahead token.
$this->tokenStartStack[$stackPos] = $this->tokenPos;
}
}
else {
/* error */
switch ($this->errorState) {
case 0:
$msg = $this->getErrorMessage($symbol, $state);
$this->emitError(new Error($msg, $this->getAttributesForToken($this->tokenPos)));
// Break missing intentionally
// no break
case 1:
case 2:
$this->errorState = 3;
// Pop until error-expecting state uncovered
while (!(($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) || ($action = $this->action[$idx]) === $this->defaultAction) {
// Not totally sure about this
if ($stackPos <= 0) {
// Could not recover from error
return null;
}
$state = $stateStack[--$stackPos];
//$this->tracePop($state);
}
//$this->traceShift($this->errorSymbol);
++$stackPos;
$stateStack[$stackPos] = $state = $action;
// We treat the error symbol as being empty, so we reset the end attributes
// to the end attributes of the last non-error symbol
$this->tokenStartStack[$stackPos] = $this->tokenPos;
$this->tokenEndStack[$stackPos] = $this->tokenEndStack[$stackPos - 1];
break;
case 3:
if ($symbol === 0) {
// Reached EOF without recovering from error
return null;
}
//$this->traceDiscard($symbol);
$symbol = self::SYMBOL_NONE;
break 2;
}
}
if ($state < $this->numNonLeafStates) {
break;
}
/* >= numNonLeafStates means shift-and-reduce */
$rule = $state - $this->numNonLeafStates;
}
}
throw new \RuntimeException('Reached end of parser loop');
}