Source

ocaml-niwango / parser.ml

Full commit
open Util
open ParserMonad
open Ast

let digits_string =
  many1 digit >>= fun cs ->
  return (string_of_chars cs)
  
let num =
  digits_string >>= fun z ->
  opt (keyword "." >> digits_string) >>= fun s_opt ->
  let s = Option.get_or_else "" s_opt in
  return (float_of_string(z^"."^s))

let position = map Date.of_float num

let string =
  let body1 = make_ident ((<>) '\'') in
  keyword "'" >> body1 << keyword "'"

let bool =
  (keyword "true" >> return true) <|> (keyword "false" >> return false)

let const =
     (string >>= fun s -> return (String s))
 <|> (num ^? "num" >>= fun n -> return (Num n))
 <|> (bool >>= fun b -> return (Bool b))

let ident =
  make_ident (function
    | '0'..'9' -> true
    | 'a'..'z' -> true
    | 'A'..'Z' -> true
    | '_' -> true
    | '@' -> false
    | _ -> false)

let whitespace = many (char '\n' <|> char ' ' <|> char '\t' <|> char '\r')

let rec exp() = fun _ss ->
(whitespace >>
begin
  factor()
end) _ss

and factor () = factor0() >>= fun body -> factor_next(body)

and factor0 () =
     (const >>= fun c -> return (Con c))
 <|> (ident >>= fun x -> return (Var x))
 <|> (ident >>= fun x -> args() >>= fun es -> return (Method(This, x, es)))
 <|> (keyword "[" >> sep (keyword",") (exp()) << keyword "[" >>= fun es -> return (Array es))

 (*TODO "(" expr ")" *)
(*TODO*)

and factor_next e =
      (keyword "." >> ident >>= fun x -> args() >>= fun es -> factor_next (Method(e, x, es)))
  <|> (keyword "." >> ident >>= fun x -> return (Field(e, x)))
  <|> (return e)

and args () =
  keyword "(" >> sep (keyword",") (exp()) << keyword ")"

and application () =
  let func =
    ident >>= fun f ->
    args() >>= fun as_ ->
    return (This,f,as_)
  in
  let _meth =
(*    exp() >>= fun obj ->*)
    factor0 () >>= fun obj ->
    keyword "." >>
    ident >>= fun fname ->
    args() >>= fun as_ ->
    return (obj, fname, as_)
  in
  func


let line =
  position >>= fun d ->
  keyword "::/" >>
  exp() >>= fun e ->
  return (Line(d, e))

let lines = sep1 (keyword "\n") line


let parse_file fname =
  run_file lines fname