(*
 *)

fun addone [] = []
  | addone (x::xs) = (x + 1) :: addone xs

fun stringy [] = []
  | stringy (x::xs) = (Int.toString x) :: stringy xs

fun negL [] = []
  | negL (x::xs) = (not x) :: negL xs

fun map f [] = []
  | map f (x::xs) = (f x) :: (map f xs);

val ex1 = map (fn x => (x+1)) [2,3,4];
val ex2 = map Int.toString [2,5,7];
val ex3 = map not [true, 3 > 4];

fun even x = x mod 2 = 0;

val ex4 = List.find (fn x => x = "Tim") ["Tom", "Jane"];
val ex5 = List.find (fn x => even x andalso x>10) [2,4,5,12];


val ex6 = List.filter even [1,2,3,4,5,6];

val people = [("tim",22),("john",18),("jane",25),("tim",8)];
val ex7 = List.filter (fn (nm,age) => nm <> "tim" orelse age>10) people;

val ex8 = List.exists even [2,3,5];
val ex9 = List.all even [2,4,5];


fun sum [] = 0
  | sum (x::xs) = x + (sum xs);

fun maximum [] = 0
  | maximum (x::xs) = Int.max(x,maximum xs);

fun allTrue [] = true
  | allTrue (x::xs) = x andalso (allTrue xs);

fun foldr acc base [ ] = base
  | foldr acc base (x::xs)
        = acc(x,foldr acc base xs);

fun sum xs = foldr (op +) 0 xs;
fun maximum xs = foldr Int.max 0 xs;
fun allTrue xs = foldr (fn (a,b) => a andalso b) true xs;

(* ******************************************************** *)

datatype Token
  = Id of string
  | Plus
  | Times
  | Eql
  | Int of int
  | Illegal;


fun extend x (xs, cs) = ((x::xs), cs);

(* ident: char -> char list -> (Token * char list) *)
fun ident c cs =
  let val xs = ref cs
      val x = ref c
      val ans = ref []
  in while (not(null(!xs)) andalso Char.isAlpha (hd (!xs))) do
       ( ans := !ans @ [!x]
       ; x := hd(!xs)
       ; xs := tl(!xs) );
     (Id (String.implode (!ans @ [!x])), !xs)
  end



(* literal: char -> char list -> (Token * char list)  *)
fun literal c cs =
  let val xs = ref cs
      val x = ref c
      val ans = ref []
      val _ = while (not(null(!xs)) andalso Char.isDigit (hd (!xs))) do
                ( ans := !ans @ [!x]
                ; x := hd(!xs)
                ; xs := tl(!xs) )
  in case Int.fromString (String.implode (!ans @ [!x])) of
       NONE => (Illegal,!xs)
     | SOME n => (Int n,!xs)
  end;


(* lex : char list -> (Token * char list) *)
fun lex [] = (Illegal,[])
  | lex (#" " :: cs) = lex cs
  | lex (#"+" :: cs) = (Plus,cs)
  | lex (#"*" :: cs) = (Times,cs)
  | lex (#"=" :: cs) = (Eql,cs)
  | lex (c :: cs) =
      if      Char.isAlpha c then ident c cs
      else if Char.isDigit c then literal c cs
      else (Illegal,c::cs);

fun test s =
   let val (token,cs) = lex(String.explode s)
   in (token,String.implode cs) end;


(* 
*)