Syntax trees - mattacosta/php-parser GitHub Wiki
Structure
A syntax tree is composed of three primary components. Together, they represent all of the information in a source file, including whitespace and comments.
SyntaxNode
- Nodes represent language constructs such as statements, expressions, or clauses.
- Nodes are also used to create the actual syntax tree, and may contain child nodes or tokens.
SyntaxToken
- Tokens represent the significant portions of text that is parsed. This includes keywords, variables, operators, and punctuation.
- Trivia is also attached to tokens (but not as children).
SyntaxTrivia
- Trivia represents the insignificant portions of text that is parsed. This includes whitespace and comments.
Navigation
Properties
A syntax tree can be manually navigated using the properties of the nodes that make up the tree.
Example:
// $a = $b + 1;
let statement = <ExpressionStatementSyntaxNode>statements[0];
// $a = $b + 1
let assignmentExpr = <AssignmentSyntaxNode>statement.expression;
// $a
let variable = <LocalVariableSyntaxNode>assignmentExpr.leftOperand;
// $b + 1
let binaryExpr = <BinarySyntaxNode>assignmentExpr.rightOperand;
// $b
let left = <LocalVariableSyntaxNode>binaryExpr.leftOperand;
// 1
let right = <LiteralSyntaxNode>binaryExpr.rightOperand;
Query methods
Every class derived from a SyntaxNode
also inherits methods that can be used
to explore the syntax tree.
These methods include, but are not limited to:
firstAncestorOrSelf()
firstToken()
getAncestors()
getAncestorsAndSelf()
getChildNodes()
getChildTokens()
lastToken()
Syntax visitors
SyntaxNode
objects also implement a visitor pattern, which allows a
SyntaxVisitor
or SyntaxTransform
to process an element of the syntax tree
without knowing its structure beforehand. For example, the SyntaxWalker
class (which is a specific kind of SyntaxVisitor
) can be used to recursively
navigate every node and its children.
Example:
/**
* Usage:
* let collector = new UseDeclarationCollector();
* collector.visit(root);
*/
class UseDeclarationCollector extends SyntaxWalker {
protected imports: UseDeclarationSyntaxNode[] = [];
/**
* Overrides `SyntaxWalker.visitUseDeclaration()`.
*/
public visitUseDeclaration(node: UseDeclarationSyntaxNode) {
imports.push(node);
}
}