include import "./lib/parsers.ml"
|
|
open import "prelude.ml"
|
|
|
|
let lex = run_parser
|
|
|
|
let line_comment () =
|
|
let! _ = symbol "--"
|
|
let rec go =
|
|
let! x = map (const "\n") eof <|> char
|
|
if x == "\n" then
|
|
pure ()
|
|
else
|
|
go
|
|
go
|
|
|
|
let whitepiece : forall 'm. monad 'm => parser_t 'm () =
|
|
(try (void @@ one_of " \n\v\t\r") <|> try (line_comment ()))
|
|
<?> "white space"
|
|
|
|
let whitespace : forall 'm. monad 'm => parser_t 'm () =
|
|
void (many whitepiece)
|
|
|
|
let lexeme p =
|
|
let! _ = whitespace
|
|
p
|
|
|
|
let oparen : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "(")
|
|
let cparen : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol ")")
|
|
let comma : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol ",")
|
|
let semi : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol ";")
|
|
let osquare : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "[")
|
|
let csquare : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "]")
|
|
let obrace : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "{")
|
|
let cbrace : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "}")
|
|
let back : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "\\")
|
|
let arrow : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "->")
|
|
let darrow : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "=>")
|
|
let equals : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "=")
|
|
let pipe : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "|")
|
|
let dcolon : forall 'm. monad 'm => parser_t 'm () = try @@ void @@ lexeme (symbol "::")
|
|
|
|
let small : forall 'm. monad 'm => parser_t 'm string =
|
|
try (satisfy (fun c -> "a" <= c && c <= "z") <|> symbol "_") <?> "small letter"
|
|
|
|
let big : forall 'm. monad 'm => parser_t 'm string =
|
|
try (satisfy (fun c -> "A" <= c && c <= "Z")) <?> "big letter"
|
|
|
|
let iskw = function
|
|
| "case"
|
|
| "class"
|
|
| "data"
|
|
| "default"
|
|
| "deriving"
|
|
| "do"
|
|
| "else"
|
|
| "if"
|
|
| "import"
|
|
| "in"
|
|
| "infix"
|
|
| "infixl"
|
|
| "infixr"
|
|
| "instance"
|
|
| "let"
|
|
| "module"
|
|
| "newtype"
|
|
| "of"
|
|
| "foreign"
|
|
| "then"
|
|
| "type"
|
|
| "where"
|
|
| "_" -> true
|
|
| _ -> false
|
|
|
|
let isreserved = function
|
|
| "=" | "=>" | "->" | "|" -> true
|
|
| _ -> false
|
|
|
|
let varid : forall 'm. monad 'm => parser_t 'm string =
|
|
flip (<?>) "variable name" # lexeme @@
|
|
let! c = small
|
|
let! cs =
|
|
many_fold (^) "" (small <|> big <|> try (symbol "'"))
|
|
<|> pure ""
|
|
let id = c ^ cs
|
|
if iskw id then
|
|
unexpected id
|
|
else
|
|
pure id
|
|
|
|
let conid : forall 'm. monad 'm => parser_t 'm string =
|
|
flip (<?>) "constructor name" # lexeme @@
|
|
let! c = big
|
|
let! cs =
|
|
many_fold (^) "" (small <|> big <|> try (symbol "'"))
|
|
<|> pure ""
|
|
pure (c ^ cs)
|
|
|
|
let tyvar = varid
|
|
let tycon = conid
|
|
let tycls = conid
|
|
|
|
let keyword c = lexeme (symbol c) <?> "``" ^ c ^ "''"
|
|
|
|
let operator : forall 'm. monad 'm => parser_t 'm string =
|
|
flip (<?>) "operator" # lexeme @@
|
|
let! c = one_of "!#$%&*+./<=>?@\\^|-~"
|
|
let! cs = many_fold (^) "" (one_of ":!#$%&*+./<=>?@\\^|-~")
|
|
let op = c ^ cs
|
|
if isreserved op then
|
|
unexpected op
|
|
else
|
|
pure op
|
|
|
|
let digit : forall 'm. monad 'm => parser_t 'm string =
|
|
satisfy (fun c -> "0" <= c && c <= "9") <?> "digit"
|
|
|
|
let hexit : forall 'm. monad 'm => parser_t 'm string =
|
|
digit
|
|
<|> satisfy (fun c -> "a" <= c && c <= "f")
|
|
<|> satisfy (fun c -> "A" <= c && c <= "F")
|
|
|
|
let integer : forall 'm. monad 'm => parser_t 'm int =
|
|
let decimal =
|
|
let! c = digit
|
|
let! cs = many_fold (^) "" digit
|
|
pure (c ^ cs)
|
|
let hexadecimal =
|
|
let! _ = symbol "0x"
|
|
let! c = hexit
|
|
let! cs = many_fold (^) "" hexit
|
|
pure ("0x" ^ c ^ cs)
|
|
let! c = (lexeme (try hexadecimal <|> decimal)) <?> "hex or decimal integer"
|
|
match parse_int c with
|
|
| None -> error "no parse"
|
|
| Some x -> pure x
|
|
|
|
let string : forall 'm. monad 'm => parser_t 'm string =
|
|
flip (<?>) "string literal" # lexeme @@
|
|
let parse_escape = function
|
|
| "n" -> pure "\n"
|
|
| "t" -> pure "\t"
|
|
| "\"" -> pure "\""
|
|
| a -> unexpected ("escape sequence " ^ a)
|
|
let str_ent =
|
|
satisfy (fun p -> p <> "\"" && p <> "\\")
|
|
<|> ( let! _ = try (symbol "\\")
|
|
let! e = char
|
|
parse_escape e)
|
|
symbol "\"" *> many_fold (^) "" str_ent <* symbol "\""
|