let prelude = import! std.prelude let { Expr } = import! "examples/lisp/types.glu" let char = import! std.char let { List } = import! std.list let { Result } = import! std.result let string = import! std.string let float = import! std.float let int = import! std.int let { Parser, fail, between, lazy_parser, many, one_of, satisfy, spaces, token, recognize, take1, skip_many, skip_many1, ? } = import! std.parser let { (<>) } = import! std.prelude let { Applicative, (<*), (*>), map2, wrap } = import! std.applicative let { map } = import! std.functor let { (<|>) } = import! std.alternative let { flat_map } = import! std.monad let atom : Parser Expr = let symbol = one_of "!#$%&|*+-/:<=>?@^_~" let alpha = satisfy char.is_alphabetic let alpha_num = satisfy char.is_alphanumeric map (\x -> Atom x) (recognize ((alpha <|> symbol) *> skip_many (alpha_num <|> symbol))) let parse_parser p f msg : Parser a -> (String -> Result () b) -> String -> Parser b = do s = recognize p match f s with | Ok i -> wrap i | Err _ -> fail ("Expected " <> msg) let int_parser : Parser Expr = map (\i -> Int i) (parse_parser (skip_many1 (satisfy char.is_numeric)) int.parse "integer") let float_parser : Parser Expr = let number = skip_many1 (satisfy char.is_numeric) map (\f -> Float f) (parse_parser (number *> token '.' *> number) float.parse "float") rec let list _ : () -> Parser Expr = let e = expr () between (token '(') (token ')') (spaces *> map (\x -> List x) (many e)) let expr _ : () -> Parser Expr = (atom <|> float_parser <|> int_parser <|> lazy_parser list) <* spaces in { expr = spaces *> lazy_parser expr, }