Thursday, November 20, 2025

A (Minimal) Lisp Interpreter written in Python (Tahsin's First New Programming Language)

 

import operator as op


# 1. Tokenizer: split input string into tokens

def tokenize(s):

    return s.replace('(', ' ( ').replace(')', ' ) ').split()


# 2. Parser: convert tokens into nested Python lists (AST)

def parse(tokens):

    if len(tokens) == 0:

        raise SyntaxError("Unexpected EOF")

    token = tokens.pop(0)

    if token == '(':

        L = []

        while tokens[0] != ')':

            L.append(parse(tokens))

        tokens.pop(0)  # remove ')'

        return L

    elif token == ')':

        raise SyntaxError("Unexpected )")

    else:

        return atom(token)


# 3. Atom: numbers become int/float, others are symbols (strings)

def atom(token):

    try:

        return int(token)

    except ValueError:

        try:

            return float(token)

        except ValueError:

            return str(token)


# 4. Environment: built-in functions

def standard_env():

    env = {}

    env.update({

        '+': op.add,

        '-': op.sub,

        '*': op.mul,

        '/': op.truediv,

        'eq?': op.eq,

        'lt?': op.lt,

        'gt?': op.gt,

        'print': print

    })

    return env


# 5. Evaluator

def eval(x, env):

    if isinstance(x, str):          # variable reference

        return env[x]

    elif not isinstance(x, list):   # constant literal

        return x

    elif x[0] == 'define':          # (define var expr)

        (_, var, expr) = x

        env[var] = eval(expr, env)

    else:                           # procedure call

        proc = eval(x[0], env)

        args = [eval(arg, env) for arg in x[1:]]

        return proc(*args)


# 6. REPL

def repl():

    env = standard_env()

    while True:

        try:

            expr = input('lisp> ')

            if expr.strip() == "exit":

                break

            val = eval(parse(tokenize(expr)), env)

            if val is not None:

                print(val)

        except Exception as e:

            print("Error:", e)


if __name__ == "__main__":

    repl()


🧪 Example Usage

lisp> (+ 12 7)
19
lisp> (* 4 5)
20
lisp> (define x 10)
lisp> (+ x 7)
17
lisp> (print "Hello, Syed")
Hello, Syed

No comments:

Post a Comment

Mini RDBMS (with persistent storage) using only Python Standard Library

Mini RDBMS (with persistent storage) using only the Python Standard Library import re import json import os from typing import Any, Dict, Li...