mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2024-11-26 20:14:46 +01:00
Build node attributes inside semantic action methods
Minor performance improvement for parsing, also allows to access attributes with higher granulity in the parser, though this is not currently done. * #n can now be used to access the stack position of a token. $n is the same as $this->semStack[#n]. (Post-translate $n will actually be the stack position.) * $attributeStack is now $this->startAttributeStack and $endAttributes is now $this->endAttributes. * Attributes for a node are now computed inside the individual reduction methods, instead of being passed as a parameter. Accessible through the attributes() macro.
This commit is contained in:
parent
e30c3ac01b
commit
6996db1e3a
@ -2,8 +2,8 @@
|
||||
$meta #
|
||||
#semval($) $this->semValue
|
||||
#semval($,%t) $this->semValue
|
||||
#semval(%n) $this->semStack[$this->stackPos-(%l-%n)]
|
||||
#semval(%n,%t) $this->semStack[$this->stackPos-(%l-%n)]
|
||||
#semval(%n) $this->stackPos-(%l-%n)
|
||||
#semval(%n,%t) $this->stackPos-(%l-%n)
|
||||
#include;
|
||||
|
||||
namespace PhpParser;
|
||||
@ -87,7 +87,7 @@ class Parser extends ParserAbstract
|
||||
#endif
|
||||
#reduce
|
||||
|
||||
protected function reduceRule%n($attributes) {
|
||||
protected function reduceRule%n() {
|
||||
%b
|
||||
}
|
||||
#noact
|
||||
|
@ -43,6 +43,7 @@ $grammarCode = resolveConstants($grammarCode);
|
||||
$grammarCode = resolveNodes($grammarCode);
|
||||
$grammarCode = resolveMacros($grammarCode);
|
||||
$grammarCode = resolveArrays($grammarCode);
|
||||
$grammarCode = resolveStackAccess($grammarCode);
|
||||
|
||||
file_put_contents($tmpGrammarFile, $grammarCode);
|
||||
|
||||
@ -83,7 +84,7 @@ function resolveNodes($code) {
|
||||
$paramCode .= $param . ', ';
|
||||
}
|
||||
|
||||
return 'new Node\\' . $matches['name'] . '(' . $paramCode . '$attributes)';
|
||||
return 'new Node\\' . $matches['name'] . '(' . $paramCode . 'attributes())';
|
||||
},
|
||||
$code
|
||||
);
|
||||
@ -102,6 +103,11 @@ function resolveMacros($code) {
|
||||
$matches['args']
|
||||
);
|
||||
|
||||
if ('attributes' == $name) {
|
||||
assertArgs(0, $args, $name);
|
||||
return '$this->startAttributeStack[#0] + $this->endAttributes';
|
||||
}
|
||||
|
||||
if ('init' == $name) {
|
||||
return '$$ = array(' . implode(', ', $args) . ')';
|
||||
}
|
||||
@ -185,6 +191,12 @@ function resolveArrays($code) {
|
||||
);
|
||||
}
|
||||
|
||||
function resolveStackAccess($code) {
|
||||
$code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code);
|
||||
$code = preg_replace('/#(\d+)/', '$$1', $code);
|
||||
return $code;
|
||||
}
|
||||
|
||||
function moveFileWithDirCheck($fromPath, $toPath) {
|
||||
$dir = dirname($toPath);
|
||||
if (!is_dir($dir)) {
|
||||
|
@ -176,7 +176,7 @@ inner_statement:
|
||||
| function_declaration_statement { $$ = $1; }
|
||||
| class_declaration_statement { $$ = $1; }
|
||||
| T_HALT_COMPILER
|
||||
{ throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $attributes); }
|
||||
{ throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
|
||||
;
|
||||
|
||||
statement:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -78,10 +78,14 @@ abstract class ParserAbstract
|
||||
protected $lexer;
|
||||
/** @var mixed Temporary value containing the result of last semantic action (reduction) */
|
||||
protected $semValue;
|
||||
/** @var array Semantic value stack (contains values of tokens and semantic action results) */
|
||||
protected $semStack;
|
||||
/** @var int Position in stacks (state stack, semantic value stack, attribute stack) */
|
||||
protected $stackPos;
|
||||
/** @var array Semantic value stack (contains values of tokens and semantic action results) */
|
||||
protected $semStack;
|
||||
/** @var array[] Start attribute stack */
|
||||
protected $startAttributeStack;
|
||||
/** @var array End attributes of last *shifted* token */
|
||||
protected $endAttributes;
|
||||
|
||||
/** @var bool Whether to throw on first error */
|
||||
protected $throwOnError;
|
||||
@ -131,11 +135,11 @@ abstract class ParserAbstract
|
||||
// From the first token only the startAttributes are taken and from the last only
|
||||
// the endAttributes. Both are merged using the array union operator (+).
|
||||
$startAttributes = array('startLine' => 1);
|
||||
$endAttributes = array();
|
||||
$this->endAttributes = array();
|
||||
|
||||
// In order to figure out the attributes for the starting token, we have to keep
|
||||
// them in a stack
|
||||
$attributeStack = array($startAttributes);
|
||||
$this->startAttributeStack = array($startAttributes);
|
||||
|
||||
// Start off in the initial state and keep a stack of previous states
|
||||
$state = 0;
|
||||
@ -174,7 +178,7 @@ abstract class ParserAbstract
|
||||
));
|
||||
}
|
||||
|
||||
$attributeStack[$this->stackPos] = $startAttributes;
|
||||
$this->startAttributeStack[$this->stackPos] = $startAttributes;
|
||||
|
||||
//$this->traceRead($symbol);
|
||||
}
|
||||
@ -199,8 +203,8 @@ abstract class ParserAbstract
|
||||
++$this->stackPos;
|
||||
$stateStack[$this->stackPos] = $state = $action;
|
||||
$this->semStack[$this->stackPos] = $tokenValue;
|
||||
$attributeStack[$this->stackPos] = $startAttributes;
|
||||
$endAttributes = $nextEndAttributes;
|
||||
$this->startAttributeStack[$this->stackPos] = $startAttributes;
|
||||
$this->endAttributes = $nextEndAttributes;
|
||||
$symbol = self::SYMBOL_NONE;
|
||||
|
||||
if ($errorState) {
|
||||
@ -231,10 +235,7 @@ abstract class ParserAbstract
|
||||
//$this->traceReduce($rule);
|
||||
|
||||
try {
|
||||
$this->{'reduceRule' . $rule}(
|
||||
$attributeStack[$this->stackPos - $this->ruleToLength[$rule]]
|
||||
+ $endAttributes
|
||||
);
|
||||
$this->{'reduceRule' . $rule}();
|
||||
} catch (Error $e) {
|
||||
if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) {
|
||||
$e->setStartLine($startAttributes['startLine']);
|
||||
@ -256,7 +257,7 @@ abstract class ParserAbstract
|
||||
++$this->stackPos;
|
||||
$stateStack[$this->stackPos] = $state;
|
||||
$this->semStack[$this->stackPos] = $this->semValue;
|
||||
$attributeStack[$this->stackPos] = $startAttributes;
|
||||
$this->startAttributeStack[$this->stackPos] = $startAttributes;
|
||||
} else {
|
||||
/* error */
|
||||
switch ($errorState) {
|
||||
|
Loading…
Reference in New Issue
Block a user