Skip to content

Instantly share code, notes, and snippets.

@rightfold
Last active August 29, 2015 14:20
Show Gist options
  • Save rightfold/5175bfc6157286a24913 to your computer and use it in GitHub Desktop.
Save rightfold/5175bfc6157286a24913 to your computer and use it in GitHub Desktop.
ast = require("./ast")
{fold} = require("prelude-ls")
error = {}
tokens = null
read = ->
if tokens.length == 0
then {type: \eof, value: void}
else tokens.shift!
expect = (type) ->
token = read!
if token.type != type
throw error
token
backtrack = (body) ->
local-tokens = tokens.slice!
try
body!
catch
tokens := local-tokens
throw e
many = (parser) ->
result = []
loop
try
result.push(backtrack(parser))
catch
if e == error
then return result
else throw e
one-of = (...parsers) ->
for parser in parsers
try
return backtrack(parser)
catch
if e == error
then continue
else throw e
throw error
decl = -> one-of(proc-decl)
proc-decl = ->
expect(\proc)
name = expect(\identifier).value
expect(\lparen)
expect(\rparen)
expect(\eq)
body = expr!
expect(\semicolon)
new ast.ProcDecl(name, body)
expr = -> call-expr!
call-expr = ->
suffix = ->
expect(\lparen)
arguments_ = [expr!]
expect(\rparen)
(callee) -> new ast.CallExpr(callee, arguments_)
callee = primary-expr!
many(suffix) |> fold (|>), callee
primary-expr = -> one-of(name-expr, string-expr)
name-expr = -> new ast.NameExpr(expect(\identifier).value)
string-expr = -> new ast.StringExpr(expect(\string).value)
parse = (local-tokens) ->
tokens := local-tokens
decls = many(decl)
if tokens.length > 0
throw Error("expected EOF")
decls
module.exports = parse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment