MyNixOS website logo
Description

A programming language with no semantics.

An s-expression parser and abstract syntax tree for a programming language with no semantics. If you wanted to write an interpreter or compiler you convert the AST into your own.

Snail

A no-semantics programming language for gastropods.

Why?

My colleagues and I are going to start working through Types and Programming Languages. In the book you implement languages of varying feature sets. The book implements these languages in OCaml, however I had this Lisp parser essentially ready for awhile. There are a handful of "Write you a Scheme Interpreters"-like tutorials and they all use a parser relatively similar to this one. However, there are some pretty subtle issues with most of the ones I have seen. For example, the two examples below parse as two lexemes in a lot of examples. Even Haskell's parser has this issue!

(1a)
(1 a)

Is this really a programming language?

From the "Programming language" Wikipedia page,

A programming language is a system of notation for writing computer programs.

The description of a programming language is usually split into the two components of syntax (form) and semantics (meaning)

Snail is used for writing interpreters or compilers. However, it doesn't define any semantics. So, maybe?

Syntax (form)

Snail describes valid lexemes, text literals, and s-expressions. The valid lexemes are approximately from R5RS Scheme but this may change in the future. We also use Haskell's line and block comments. Here is a valid snail program,

-- Prints `hello "world"` to the console
(print "hello \"world\"")

-- Prints 3 to the console
(print (+ 1 2))

{-
  Defines a function to add two numbers
  Applies the function to generate 3
  Prints 3 to the console
-}
(let
  (f (lambda (x y) (+ x y)))
  (print (f 2 1)))

(quote hello)

(nil)

(print true)

(print false)

-- end comment

Reminder, this program has no semantics. It is your job to take Snail's Abstract Syntax Tree (AST) and define the semantics of an interpreter or compiler.

Getting the AST

You have two options: readSnailFile or parseSnail.

readSnailFile can be used like this, assuming you have put some valid snail into a file ./hello.snail,

import Snail

printSnail :: IO ()
printSnail = do
  eResults <- readSnailFile "./hello.snail"
  case eResults of
    Right ast -> print ast
    Left failureString -> print failureString

parseSnail doesn't require IO the only parameter is Text. This is useful for one-line programs, e.g.,

{-# LANGUAGE OverloadedStrings #-}

import Snail

example :: Either String [SnailAst]
example = parseSnail "(print false)"

Example Interpreters

  1. The arith language from Types and Programming Languages: https://github.com/chiroptical/snail-arith/blob/main/src/Lib.hs
  2. Languages from essentials-of-compilation: https://github.com/chiroptical/essentials-of-compilation (each chapter is a module)
Metadata

Version

0.1.2.1

License

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows