What is a Syntax Tree?
A syntax tree (also called an expression tree, or more generally an Abstract Syntax Tree/AST) captures the grammatical structure of an expression or piece of code, rather than its raw text. For arithmetic expressions specifically, every operator becomes an internal node with its operands as children, and every literal value becomes a leaf. The shape of the tree, not the order characters appear on the page, is what encodes precedence and grouping.
How Does It Work?
Building one from an infix expression like "3 + 4 * (2 - 1)" requires a parser that respects operator precedence and parentheses — multiplication and division bind tighter than addition and subtraction, and anything inside parentheses is parsed as its own self-contained sub-expression first. A common approach is recursive-descent parsing: one function handles addition/subtraction terms, which calls another handling multiplication/division factors, which calls another handling numbers and parenthesized groups — the recursive call structure mirrors the grammar's precedence levels directly.
Once built, the tree makes evaluation and notation conversion almost mechanical, because each is just a different tree traversal. Evaluating the expression is a post-order traversal: recursively compute both children's values first, then apply the operator to combine them — by the time an operator node is processed, both its operands are already known. Reading the tree with a pre-order traversal produces prefix notation, and post-order traversal produces postfix notation; both eliminate the need for parentheses or precedence rules entirely, since the tree structure alone determines evaluation order.
Algorithm Steps
- Tokenize the input into numbers, operators, and parentheses
- Parse recursively, respecting precedence:
- Parse an expression as a sequence of terms joined by + or -
- Parse a term as a sequence of factors joined by * or /
- Parse a factor as either a number, or a parenthesized sub-expression parsed from scratch
- Each operator encountered becomes an internal node whose children are the two operands just parsed
- To evaluate: post-order traverse the tree, computing both children before applying the operator at each node
Time Complexity
- Parsing Time: O(n) — each token is consumed exactly once by the recursive-descent parser.
- Evaluation Time: O(n) — each node in the tree is visited exactly once during the post-order traversal.
- Space Complexity: O(n) for the tree, plus O(h) recursion stack depth for parsing and evaluating.
Time Complexity Analysis
Syntax trees are the intermediate representation nearly every compiler and interpreter builds after parsing source code, before generating machine code or bytecode from it. The same idea powers calculator apps, spreadsheet formula engines, and query planners in databases — anywhere text needs to become something with an unambiguous, machine-processable structure.