diff --git a/lectures/10/client.ml b/lectures/10/client.ml new file mode 100644 index 0000000..ef4e85a --- /dev/null +++ b/lectures/10/client.ml @@ -0,0 +1,41 @@ +(* +org(123,BCIT) +org(345,Hell Holdings\, Ltd) +person(666,name(monty,burns)) +org(456,Ocaml \(LLC\)) +*) +open Angstrom + +type name = Name of string * string +type client = Person of int * name | Org of int * string + +let name first last = Name (first, last) +let person id name = Person (id, name) +let org id name = Org (id, name) + +let a_char = + (string "\\(" *> return '(') <|> + (string "\\)" *> return ')') <|> + (string "\\," *> return ',') <|> + (string "\\n" *> return '\n') <|> + satisfy (fun c -> c <> '(' && c <> ')' && c <> ',' && c <> '\n') + +let a_string = + many1 a_char >>| fun l -> l |> List.to_seq |> String.of_seq + + +let uint = take_while1 (function | '0'..'9' -> true | _ -> false) >>| int_of_string + +let a_name = name <$> string "name(" *> a_string <* char ',' <*> a_string <* char ')' + +let a_person = person <$> string "person(" *> uint <* char ',' <*> a_name <* char ')' + +let an_org = org <$> string "org(" *> uint <* char ',' <*> a_string <* char ')' + +let a_client = a_person <|> an_org + +let parse file = + let ic = open_in file in + let content = really_input_string ic (in_channel_length ic) in + parse_string ~consume:All (many (a_client <* end_of_line)) content + diff --git a/lectures/10/data b/lectures/10/data new file mode 100644 index 0000000..2057fed --- /dev/null +++ b/lectures/10/data @@ -0,0 +1,4 @@ +org(123,BCIT) +org(345,Hell Holdings\, Ltd) +person(666,name(monty,burns)) +org(456,Ocaml \(LLC\)) diff --git a/lectures/10/utils.ml b/lectures/10/utils.ml new file mode 100644 index 0000000..be80695 --- /dev/null +++ b/lectures/10/utils.ml @@ -0,0 +1,42 @@ +open Angstrom + +let is_digit = function | '0'..'9' -> true | _ -> false + +let is_space = function | ' ' | '\t' -> true | _ -> false + +let ws = take_while is_space + +let ws1 = take_while1 is_space + +let uint_str = take_while1 is_digit + +let uint_num = uint_str >>| int_of_string + +let sign = + peek_char >>= function + | Some '+' -> advance 1 >>| fun () -> "+" + | Some '-' -> advance 1 >>| fun () -> "-" + | Some c when is_digit c -> return "+" + | _ -> fail "digit or sign expected" + +let int_str = + let* s = sign in + let* n = uint_str in + return (s ^ n) + +let int_num = int_str >>| int_of_string + +let dot = + peek_char >>= function + | Some '.' -> advance 1 >>| fun () -> true + | _ -> return false + +let float_str = + let* n = int_str in + let* is_dot = dot in + if is_dot then + let* f = uint_str in return (n ^ "." ^ f) + else + return n + +let float_num = float_str >>| float_of_string