| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- open Types
- type token = LPAREN | RPAREN | ID of string | HASH | EXCLAM | PLUS | MINUS
- let tokenize next_char emit =
- let buf = Buffer.create 32 in
- let emit_buf () =
- match Buffer.length buf with
- | 0 -> ()
- | _ ->
- emit (ID (Buffer.contents buf));
- Buffer.clear buf
- in
- let nobuf () =
- assert (Buffer.length buf = 0)
- in
- let rec n () =
- match next_char () with
- | Some '(' -> nobuf (); emit LPAREN; n ()
- | Some ')' -> emit_buf (); emit RPAREN; n ()
- | Some ';' -> emit_buf (); n ()
- | Some '#' -> nobuf (); emit HASH; n ()
- | Some '!' -> nobuf (); emit EXCLAM; n ()
- | Some '+' -> nobuf (); emit PLUS; n ()
- | Some '-' -> nobuf (); emit MINUS; n ()
- | Some (' ' | '\t') -> emit_buf (); n ()
- | Some c -> Buffer.add_char buf c; n ()
- | None -> emit_buf ()
- in n ()
- let program_of_list = function
- | [] -> Empty
- | [p] -> p
- | p -> Concat p
- type exp = E_basic | E_jump | E_ptest | E_ntest
- let parse tokenize =
- let stack = ref [ref []] in
- let expect = ref E_basic in
- let append p =
- let lst = List.hd !stack in
- lst := p :: !lst
- in
- let handler = function
- | ID s ->
- let p =
- match !expect with
- | E_basic -> Basic s
- | E_jump -> Jump (int_of_string s)
- | E_ptest -> Ptest s
- | E_ntest -> Ntest s
- in
- append (Primitive p);
- expect := E_basic
- | EXCLAM ->
- append (Primitive Terminate)
- | HASH ->
- expect := E_jump
- | PLUS ->
- expect := E_ptest
- | MINUS ->
- expect := E_ntest
- | LPAREN ->
- stack := ref [] :: !stack
- | RPAREN ->
- let body = List.rev !(List.hd !stack) in
- stack := List.tl !stack;
- append (Repeat (program_of_list body))
- in
- tokenize handler;
- Concat (List.rev !(List.hd !stack))
- let parse_string s =
- let i = ref 0 in
- let next_char () =
- if !i = String.length s
- then None
- else (incr i; Some (String.get s (!i - 1)))
- in
- parse (tokenize next_char)
|