Clone this repo:

Branches

  1. 231861d README by Sketch🕴️ · 5 weeks ago master
  2. 5194126 Resurrect old plan by Sketch🕴️ · 5 weeks ago
  3. 5a0d94f Session: 02 by Sketch🕴️ · 5 weeks ago
  4. 0279013 Step 7: Add integration tests for function definitions - define+call, multi-param, cross-function, nested, errors by Sketch🕴️ · 5 weeks ago
  5. 17f2439 Step 6: Update REPL to use ParseLine + Evaluator; add function definition REPL tests by Sketch🕴️ · 5 weeks ago

matheval

A math expression evaluator with user-defined functions and an interactive REPL, written in Go.

Features

  • Arithmetic operators: +, -, *, /
  • Parentheses for grouping
  • Floating point numbers (including .5 syntax)
  • Correct operator precedence (* and / bind tighter than + and -)
  • Left-to-right associativity
  • User-defined functions with f(x) = x + 1 syntax
  • Multi-parameter functions: f(x, y) = x + y
  • Functions can call other user-defined functions (late binding)
  • Clear error messages with position reporting

Build

go build -o matheval ./cmd/matheval

Usage

Run the REPL:

./matheval

Then type expressions and define functions:

>> 2 + 3 * 4
14
>> (2 + 3) * 4
20
>> 7 / 2
3.5
>> 1 / 0
error: division by zero
>> square(x) = x * x
defined square
>> square(5)
25
>> add(x, y) = x + y
defined add
>> add(2, 3)
5
>> hyp(a, b) = square(a) + square(b)
defined hyp
>> hyp(3, 4)
25

Press Ctrl+D (EOF) to exit.

You can also pipe input:

echo "2 + 3" | ./matheval

Architecture

Input string → Lexer → Parser → AST → Evaluator → Result
PackageResponsibility
tokenToken types and data structures
lexerTokenizes input string
astAST node types (NumberLit, BinaryExpr, Ident, FuncCall, FuncDef)
parserRecursive-descent parser (expressions and function definitions)
evaluatorStateful evaluator with function registry
replRead-eval-print loop with persistent state

Grammar

line     → funcdef | expr
funcdef  → IDENT '(' params ')' '=' expr
params   → IDENT (',' IDENT)*
expr     → term (('+' | '-') term)*
term     → factor (('*' | '/') factor)*
factor   → NUMBER | IDENT '(' args ')' | IDENT | '(' expr ')'
args     → expr (',' expr)*

Function Rules

  • Define: name(params) = body — body is any expression using the parameters
  • Call: name(args) — arguments are arbitrary expressions
  • Redefinition: Not allowed (returns an error)
  • Cross-calling: Functions can call other user-defined functions
  • Late binding: References resolved at call time, not definition time

Tests

go test ./...

This runs unit tests for each package plus integration tests covering the full pipeline.