0Pricing
Lua Academy · Lesson

Simple Expression Parser

Build a recursive descent parser for arithmetic expressions in pure Lua.

Simple Expression Parser is a free Lua Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Goal: Parse Arithmetic Expressions

Build a recursive descent parser in pure Lua that parses and evaluates expressions like 3 + 4 * (2 - 1), respecting operator precedence.

Tokenizer

First, tokenize the input into numbers, operators, and parentheses.

local function tokenize(expr)
  local tokens = {}
  for tok in expr:gmatch("[%d%.]+|[%+%-%*/%(%)%^]|%S") do
    tokens[#tokens+1] = tok
  end
  return tokens
end

Improved Tokenizer

A more robust tokenizer using gmatch patterns.

local function tokenize(expr)
  local tokens = {}
  for tok in expr:gmatch("%d+%.?%d*|[%+%-%*/%(%)%^]") do
    tokens[#tokens+1] = tok
  end
  return tokens
end

Parser State

The parser carries a token list and a position. Helper functions peek and consume advance through tokens.

local function newParser(tokens)
  local pos = 1
  local function peek() return tokens[pos] end
  local function consume() pos = pos + 1; return tokens[pos-1] end
  return {peek=peek, consume=consume}
end

Grammar for Expressions

The grammar respects precedence:

  • expr = term ((+ | -) term)*
  • term = factor ((* | /) factor)*
  • factor = number | (expr) | -factor

Parsing Terms

Parse additive expressions by parsing terms and folding +/- left to right.

local parseExpr, parseTerm, parseFactor
parseExpr = function(p)
  local val = parseTerm(p)
  while p.peek() == "+" or p.peek() == "-" do
    local op = p.consume()
    local right = parseTerm(p)
    if op == "+" then val = val + right
    else val = val - right end
  end
  return val
end

Parsing Factors

Parse multiplicative expressions, including exponentiation.

parseTerm = function(p)
  local val = parseFactor(p)
  while p.peek() == "*" or p.peek() == "/" do
    local op = p.consume()
    local right = parseFactor(p)
    if op == "*" then val = val * right
    else val = val / right end
  end
  return val
end

Parsing Numbers and Parentheses

Parse atoms: literals, parenthesized sub-expressions, and unary negation.

parseFactor = function(p)
  local tok = p.peek()
  if tok == "(" then
    p.consume()  -- (
    local val = parseExpr(p)
    p.consume()  -- )
    return val
  elseif tok == "-" then
    p.consume()
    return -parseFactor(p)
  else
    return tonumber(p.consume())
  end
end

Putting It Together

Tokenize, parse, and evaluate an expression.

local function eval(expr)
  local tokens = tokenize(expr)
  local parser = newParser(tokens)
  return parseExpr(parser)
end
print(eval("3 + 4 * 2"))      -- 11
print(eval("(3 + 4) * 2"))    -- 14
print(eval("2 ^ 10"))         -- 1024 (if ^ is supported)

Extending the Parser

Add variables, functions, comparison operators, and string literals by extending the grammar and adding new cases to parseFactor.

Error Reporting

Track line and column in the tokenizer. Raise meaningful errors: "Expected ')' at position 7, got '+'".

Parser Generators

For complex grammars, use parser generators like LPEG (Parsing Expression Grammars). LPEG is much more powerful and expressive than hand-written recursive descent for large grammars.

Parser Question

What does a recursive descent parser use to enforce operator precedence?

Recap: Simple Expression Parser

A recursive descent parser uses one function per grammar rule, naturally enforcing operator precedence through the call hierarchy. Tokenize first, then implement expr → term → factor functions. Extend with variables and functions for a full expression language.

Frequently asked questions

Is the “Simple Expression Parser” lesson free?

Yes — the full text of “Simple Expression Parser” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.

What will I learn in “Simple Expression Parser”?

Build a recursive descent parser for arithmetic expressions in pure Lua. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Lua Academy?

No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Simple Expression Parser” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Lua Academy lesson?

Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. DSL Design Principles in Lua
  2. Operator Overloading for DSL Fluency
  3. Building a Config DSL
  4. Simple Expression Parser
← Back to Lua Academy