Abstract syntax tree 2026-10-13
An abstract syntax tree is a rooted tree recording the meaningful syntactic pieces of a program and how they fit together. A program identifier such as x, a literal value such as 2, and a node representing addition have different roles. Their arrangement answers structural questions: which program expression supplies an operand, which name is a variable assignment target, and which construct encloses another. This makes an abstract syntax tree useful to a compiler, an interpreter, and the type system that checks a program.
The word "abstract" describes what is omitted. Lexical analysis first recognizes lexical tokens, such as x, =, 2, +, 3, *, 4. A concrete parse tree can retain grammar derivation structure, including punctuation and intermediate context-free grammar categories such as expression, term and factor. An abstract syntax tree usually keeps the operation and its operands without all those grammar scaffolds. Parentheses can determine its shape without surviving as separate nodes. A parser may construct the abstract syntax tree directly; it need not first allocate a concrete parse tree.
An abstract syntax tree records programming language syntax, but does not by itself supply all programming language semantics. In a+b, the names do not reveal their current values, and + might perform addition of integers or concatenate strings. The programming language rules, name bindings, and operand types determine the meaning. In Python, successfully calling ast.parse also does not guarantee that later compilation will accept the result: parsing return 42 succeeds, but compiling that statement outside a function fails. [ref]
An abstract syntax tree is not machine code. Its nodes describe language constructs. A compiler can check and transform this structure before translating it into executable instructions; an interpreter can evaluate an appropriate tree directly. The little evaluator below demonstrates this distinction without pretending to implement an entire programming language.
Consider Python programs x=2+3*4 and x=(2+3)*4. Operator precedence places multiplication inside the right operand of addition in the first abstract syntax tree. The parentheses instead place addition inside the left operand of multiplication in the second. Their right-hand sides evaluate to and . No rule that simply reads all operators left to right would recover both structures. [ref]
Figure 1.
Two abstract syntax trees for variable assignment: operator precedence gives x=2+3*4 the value , while parentheses give x=(2+3)*4 the value
. Details.
These are schematic views of Python trees: Module is omitted, and the Add/Mult and Store markers are written inside their owning nodes. In the actual schema, BinOp has left, op and right fields; Assign has a list of targets and a value. Name(id='x', ctx=Store()) marks the name as a variable assignment target. Reading x in a program expression instead uses Load. A variable assignment is a statement, not an equation asserting that two values are equal. [ref]
A restricted recursive evaluator can follow those fields. It accepts only integer literal values and binary addition, subtraction and multiplication; the surrounding variable assignment remains a separate action. Using type(value) is int excludes Boolean constants, even though Python treats bool as a subclass of int.
import ast

OPS = {ast.Add: lambda a, b: a + b,
       ast.Sub: lambda a, b: a - b,
       ast.Mult: lambda a, b: a * b}

def evaluate(node):
    if isinstance(node, ast.Constant) and type(node.value) is int:
        return node.value
    if isinstance(node, ast.BinOp) and type(node.op) in OPS:
        return OPS[type(node.op)](evaluate(node.left), evaluate(node.right))
    raise ValueError("outside the integer-expression language")

for source in ("x=2+3*4", "x=(2+3)*4"):
    tree = ast.parse(source, optimize=0)
    statement = tree.body[0]
    print(statement.targets[0].id, evaluate(statement.value))
# x 14
# x 20
The children in a rooted tree have ordered roles: left and right cannot be interchanged. For subtraction, 8-3 gives while 3-8 gives . Operator associativity also matters: 8-3-1 parses as (8-3)-1, giving , whereas 8-(3-1) gives . Here the syntax groups operators to the left; this does not assert the mathematical associativity of subtraction. Operator precedence determines grouping, rather than a general permission to reorder execution. For example, Python evaluates the calls in f()+g()*h() in the order f, g, h, although the multiplication result must be ready before the outer addition. [ref]
An abstract syntax tree can retain source locations even while omitting punctuation nodes. Python records one-based line numbers and zero-based UTF-8 byte offsets, with the end offset exclusive. In x=2+3*4, the multiplication node spans offsets through , and ast.get_source_segment returns 3*4. A copied location on a folded 12 describes the original span, not text newly present in the source. Such metadata supports error messages and editing tools without making an abstract syntax tree a lossless record of formatting. [ref]
// Target: computer-science.bigb
An abstract syntax tree transformation replaces or rearranges nodes. It can simplify a program expression, insert instrumentation, or translate a language construct into simpler constructs. When intended to preserve programming language semantics, it must preserve the relevant observable behavior, including values, side effects, and failures. A changed tree can be structurally valid while changing the program's meaning.
An abstract syntax tree traversal systematically visits its nodes. A depth-first traversal of a tree that processes each child before its parent is called postorder. For the program expression 2+3*4, the schematic postorder is 2, 3, 4, Mult, Add. This order lets an evaluator obtain each operand value before applying its operation. A traversal of the entire Python schema additionally visits marker nodes such as Add and Store; this shorter list concerns only the expression nodes drawn in the figures. Visiting an abstract syntax tree is a structural operation, and is not a general model of execution: a conditional may select only one branch, while a structural visitor examines both.
Compilation 2026-10-13
The translation process performed by a compiler, which may include checking and transforming an abstract syntax tree.
Compiler 2026-10-13
A compiler translates a program into another representation, often executable instructions. Compilation can use an abstract syntax tree for checking and transformations such as constant folding before producing machine code.
Interpreter (computing) 2026-10-13
An implementation that executes a program's operations. An interpreter can work from an abstract syntax tree or another representation rather than requiring the whole program to be translated into machine code in advance.
Machine code 2026-10-13
Encoded instructions executed by a central processing unit. An abstract syntax tree instead describes programming language constructs and their nesting.
Parser 2026-10-13
A parser recognizes how text fits a programming language syntax and can construct a parse tree or abstract syntax tree.