Lua Academy · Lesson

Simple Expression Parser

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

Lesson 4 of 414 steps

Simple Expression Parser is a free Lua Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, and your progress syncs across the web and the CoddyKit app. The Lua Academy course includes 4 lessons in total.

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.

Free to start

Learn Lua with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
40
Lessons
159

Frequently Asked Questions

Is the “Simple Expression Parser” lesson free?

Yes — any 3 lessons of the Lua Academy learning path, including “Simple Expression Parser”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Lua Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

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