Skip to content

Latest commit

 

History

History
63 lines (57 loc) · 2.06 KB

parsing-expressions.md

File metadata and controls

63 lines (57 loc) · 2.06 KB

This is how I typically parse expressions. This is only here so I can point people towards it in case they ask me about it (note: this is pseudocode, obviously).

/// Parse an expression.
///
/// The precedence is an integer; HIGHER precedence binds 
/// MORE tightly, e.g. Precedenceof (/) is GREATER than 
/// Precedenceof (+). If the precedence is 0, then the token
/// is not an operator.
///
/// This handles, binary, prefix, postfix, as well as right-
/// associative operators correctly.
Parse-Expression (precedence = 0 /** Default value is 0 **/) {
    /// Actually parse an expression depending on the current
    /// token. For instance, if the current token is `if`,
    /// call Parse-If-Expression(); if it’s the number 5,
    /// create an ‘integer literal expression’, and so on.
    ///
    /// The result of this is a variable called `lhs`.
    switch (Current-Token ()) {
        case If: lhs = Parse-If-Expression();
        ...
        case Unary Operator: {
             op = Current-Token ();
             Next-Token ();
            
             /// Call ourselves recursively, passing in the
             /// precedence of ‘op’.
             operand = Parse-Expression (Precedenceof (op));
             lhs = Make-Unary-Prefix-Expr (op, operand);
        }
    }

    /// Big binary and postfix parse loop.
    while (
        /// Recalculated on every iteration.
        op = Current-Token ();
        op-pr = Precedenceof (op);
        ra = Right-Associative? (op);

        /// Loop condition.
        (op-pr > precedence) or (op-pr == precedence and ra)
    ) do {
        /// Yeet operator.
        Next-Token ();

        /// Handle postfix operators.
        if (Postfix? (op)) {
            lhs = Make-Unary-Postfix-Expr (op, lhs);
            continue;
        }

        /// To parse a binary expression, call ourselves
        /// recursively, passing in the precedence of the
        /// current token.
        rhs = Parse-Expression (op-pr);

        /// Combine the two into a binary expression.
        lhs = Make-Binary-Expr (op, lhs, rhs);
    }
}