|
|
- 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 "\""
|