As mentioned parseSourceFile
sets up the initial state and passes the work onto parseSourceFileWorker
function.
Starts by creating a SourceFile
AST node. Then it goes into parsing source code starting from the parseStatements
function. Once that returns, it then completes the SourceFile
node with additional information such as its nodeCount
, identifierCount
and such.
One of the most significant parseFoo
style functions (a concept we cover next). It switches by the current token
returned from the scanner. E.g. if the current token is a SemicolonToken
it will call out to parseEmptyStatement
to create an AST node for an empty statement.
The parser has a bunch of parserFoo
functions with bodies that create Foo
nodes. These are generally called (from other parser functions) at a time where a Foo
node is expected. A typical sample of this process is the parseEmptyStatement()
function which is used to parse out empty statements like ;;;;;;
. Here is the function in its entirety
function parseEmptyStatement(): Statement {
let node = <Statement>createNode(SyntaxKind.EmptyStatement);
parseExpected(SyntaxKind.SemicolonToken);
return finishNode(node);
}
It shows three critical functions createNode
, parseExpected
and finishNode
.
The parser's createNode
function function createNode(kind: SyntaxKind, pos?: number): Node
is responsible for creating a Node, setting up its SyntaxKind
as passed in, and set the initial position if passed in (or use the position from the current scanner state).
The parser's parseExpected
function function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean
will check that the current token in the parser state matches the desired SyntaxKind
. If not it will either report the diagnosticMessage
sent in or create a generic one of the form foo expected
. It internally uses the parseErrorAtPosition
function (which uses the scanning positions) to give good error reporting.
The parser's finishNode
function function finishNode<T extends Node>(node: T, end?: number): T
sets up the end
position for the node and additional useful stuff like the parserContextFlags
it was parsed under as well as if there were any errors before parsing this node (if there were then we cannot reuse this AST node in incremental parsing).