let numberQ s = try (int_of_string s; true) with _ -> false;; let symbolQ s = true;; (* How should this be defined? *) let rec ae_Q a = match a with [] -> false | x::xs -> (if numberQ x then match xs with [] -> true | x::xs -> ((x = "+") & (ae_Q xs)) else false);;

type exp =
    Num of int
  | Var of string
  | App of exp*exp
  | Proc of string*exp;;

exception ParserError of string;;

let rec parse stream = 
    match stream with 
      [] -> raise (ParserError "Reached EOF unexpectedly")
    | token::stream ->
      let (result,stream) = parse_exp token stream in
      (match stream with 
        [] -> result
      | _ -> raise (ParserError ("unexpected input" ^ token)))
and parse_exp token stream =
  match token with 
    x when  (numberQ x) -> (Num (int_of_string token), stream)
  | "("  -> 
   (match stream with 
    | [] -> raise (ParserError "No closing paren")
    | token::stream ->
	if token = "lambda" then
	  parse_proc stream
	else
	  parse_app token stream)
  | x when (symbolQ x) -> (Var x, stream)
  | _ -> raise (ParserError "Unrgonised token")
and parse_proc stream =
  match stream with
     bound_var::token::stream ->
      if symbolQ bound_var then
	let (body,rest) = parse_exp token stream in
       (match rest with
	   ")"::stream ->
	     (Proc (bound_var, body), stream)
         | _ -> raise (ParserError "Unexpected input at end of proc"))
      else 
	raise (ParserError "Bad variable in lambda")
and parse_app rator_first stream =
  let (rator, rest) = parse_exp rator_first stream in
  match stream with
   rand_first:: stream ->
     let (rand, rest) = parse_exp rand_first stream in
     (match stream with
       ")"::stream -> (App (rator, rand), stream)
     | _ -> raise (ParserError "Application too long"))

(* Example:

# parse ["(";"f";"1";")"];;
- : exp = App (Var "f", Num 1)

*)