Structure

function toAST (tokens: Token[]): ASTNode { let currentIndex = 0 function process (): ASTNode | null { const currentToken = tokens[currentIndex] // Process our current token, and return an AST node return null } const children: ASTNode[] = [] while (currentIndex < tokens.length) { const next = process() if (next) { children.push(next) } } return { type: ASTNodeType.Program, children } }

This may look similar to our lexer code. We're iterating over our tokens and processing them one-by-one.

Let's break this down quickly.

function process (): ASTNode | null { const currentToken = tokens[currentIndex] // Process our current token, and return an AST node return null }

We define a function called visit. This will be called each time we want to visit - or "consume" - a token.

Each token may either return a new AST Node, or nothing.

return { type: ASTNodeType.Program, children }

As mentioned in our type descriptions, we always need a root AST node. As we don't define a program 'start' in our DSL, which will be hardcoded as the first node we return.