hnq.me
all concepts
language Updated 2026-07-09 Step 2 of 6

AST

A beginner-friendly guide to understanding abstract syntax trees.

On this page 2026-07-09

A beginner-friendly guide to understanding ASTs: the tree-shaped form that helps tools and compilers understand source code.

AST stands for abstract syntax tree.

It is what source code becomes after the parser understands its structure.

tokens -> parser -> AST

Table of Contents

The Simple Idea

An AST is source code turned into structure.

Source code is text.

An AST is a tree of meaning.

The parser reads tokens and builds nodes:

function declaration
variable declaration
call expression
binary expression
return statement
identifier
literal

Once code becomes a tree, other tools can inspect it, transform it, compile it, or validate it.

Why ASTs Exist

Text is hard to reason about directly.

A tree is easier.

With an AST, a compiler can ask:

  • is this a function?
  • what is the function name?
  • what parameters does it take?
  • what statements are inside?
  • what is the left side of this expression?
  • what is the right side?
  • where is this variable used?
  • what does this import bring into scope?

Those questions are awkward when code is just a string.

They become natural when code is a tree.

Why It Is A Tree

Programs are nested.

Functions contain statements.

Blocks contain declarations.

Expressions contain smaller expressions.

Calls contain arguments.

Objects contain properties.

That nesting is why a tree fits.

Example:

2 + 3 * 4

Tree:

    +
   / \
  2   *
     / \
    3   4

The tree makes precedence visible.

3 * 4 belongs together before the result is added to 2.

A Tiny Example

Source:

const total = price * quantity

An AST might look conceptually like:

VariableDeclaration
  name: total
  value:
    BinaryExpression
      operator: *
      left: Identifier(price)
      right: Identifier(quantity)

This is not the only possible AST shape.

Different compilers choose different node structures.

But the goal is the same:

represent the program in a form tools can walk

AST vs Source Code

Source code keeps human details:

  • spacing,
  • formatting,
  • comments,
  • exact punctuation,
  • style,
  • line breaks.

An AST usually keeps semantic structure:

  • node kind,
  • names,
  • operators,
  • child nodes,
  • literal values,
  • source positions.

The AST is not trying to look like the original text.

It is trying to represent the program.

This is why formatters, linters, compilers, and analyzers often start by building a tree.

AST vs Bytecode

AST and bytecode are different layers.

An AST is close to the source language.

Bytecode is close to execution.

source -> tokens -> AST -> bytecode -> VM

The AST might say:

BinaryExpression(operator: +)

Bytecode might say:

LOAD a
LOAD b
ADD

The AST preserves structure.

Bytecode gives executable steps.

What AST Nodes Represent

Common AST nodes include:

  • program,
  • block,
  • variable declaration,
  • function declaration,
  • return statement,
  • if statement,
  • call expression,
  • member expression,
  • binary expression,
  • unary expression,
  • identifier,
  • literal,
  • import statement,
  • export statement.

Each node answers one question:

what kind of language construct is this?

The compiler can walk the tree and emit instructions based on node types.

Where AST Fits In The Pipeline

The AST is the bridge between parsing and compiling:

source text
  -> lexer
  -> tokens
  -> parser
  -> AST
  -> compiler
  -> bytecode
  -> VM

Without an AST, the compiler has to work directly from tokens or source text.

That can work for very small languages.

But an AST makes the language easier to inspect, test, and extend.

KitJS And Kitwork Notes

The AST became meaningful to me while working on Kitwork's compiler path. Tokens alone are not enough. The compiler needs shape: calls, objects, arrays, imports, functions, conditions, and expressions.

KitJS taught me that small expressions can drive UI behavior. Kitwork taught me that those expressions need a tree shape before they can become bytecode.

The AST is where code starts becoming something the runtime can transform.

My Learning Notes

ASTs made compilers feel less mysterious to me.

Before AST, source code feels like one long string.

After AST, it has shape.

While studying Kitwork's compiler pipeline, the AST became the middle layer where human syntax turns into a form the compiler can reason about.

That helped me see the pipeline more clearly:

lexer finds pieces
parser builds shape
compiler turns shape into instructions
VM runs instructions

The AST is not the final program.

It is the moment the program becomes understandable to the compiler.

Common Misunderstandings

"AST is bytecode."

No. AST is structured syntax. Bytecode is executable instruction form.

"AST keeps every detail."

Not always. It often drops formatting and comments unless the tool needs them.

"AST is only for compilers."

No. Linters, formatters, refactoring tools, syntax highlighters, code search, and static analyzers can also use tree-like representations.

"There is one correct AST."

No. AST shape is a design choice. It should serve the compiler or tool that uses it.

"AST means the code is already running."

No. An AST is still a representation. It must be interpreted, transformed, or compiled before runtime behavior happens.

Previous: lexer

Next: compiler

Related: bytecode, opcode, vm

Search