Skip to content

Instantly share code, notes, and snippets.

@cgsdev0
Last active March 30, 2026 18:02
Show Gist options
  • Select an option

  • Save cgsdev0/9d251c54dbf49092f0ed1fc78937bfd6 to your computer and use it in GitHub Desktop.

Select an option

Save cgsdev0/9d251c54dbf49092f0ed1fc78937bfd6 to your computer and use it in GitHub Desktop.
lisp parser
#!/usr/bin/env bash
# basic lisp parser that creates an AST.
# assumes valid input.
#
# it stores this AST using the file system, since
# bash doesn't really have a good way to do trees
output_path=/tmp/parsed
usage() {
cat << USAGE
usage: $0 [path_to_program]
example program:
(first (list 1 (+ 2 3) 9))
example output:
.
└── first
└── list
├── 1
├── +
│   ├── 2
│   └── 3
└── 9
USAGE
exit 1
}
source="$1"
[[ -f "$source" ]] || usage
rm -rf "$output_path"
mkdir -p "$output_path"
tokenizer() {
local acc char
emit() {
[[ -n "$acc" ]] && echo "$acc"
acc=
}
# loop character by character
while IFS= read -rn 1 char; do
char=${char:- } # newlines become spaces
case $char in
'(' | ')')
emit
echo "$char"
;;
' ') emit ;;
# accumulate characters
*) acc="${acc}${char}" ;;
esac
done
}
lexer() {
local i=0
cd "$1"
while read -r token; do
case "$token" in
'(')
read -r token
mkdir "$i $token"
pushd "$i $token" &> /dev/null
;;
')') popd &> /dev/null ;;
*) touch "$i $token" ;;
esac
((i++))
done
}
show_ast() {
cd "$1"
tree . -v --noreport \
| sed 's/[0-9]\+ //'
}
cat "$source" \
| tokenizer \
| lexer "$output_path"
show_ast "$output_path"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment