structure Tokens = Tokens

type pos = int
type svalue = Tokens.svalue
type ('a, 'b) token = ('a, 'b) Tokens.token
type lexresult = (svalue, pos) token

exception Error
val pos = ref 1
fun inc x = x := ((!x) + 1)
val error = fn x => (print("ERROR (Line "^(Int.toString (!pos))^"): " ^ x ^ "\n"); raise Error)
val eof = fn () => Tokens.EOF(!pos, !pos)
fun string_to_cstring s = "\""^(String.concat (List.map Char.toCString (String.explode s)))^"\""
%%

%header (functor LambdaLexFun(structure Tokens : Lambda_TOKENS));

alpha = [A-Za-z?];
digit = [0-9];
ws = [\ \t];


%%
\n|\013|\010	
        => (inc pos; lex());

{ws}+ 	=> (lex());
"+"	=> (Tokens.PLUS(!pos, !pos));
"-"	=> (Tokens.MINUS(!pos, !pos));
"*"	=> (Tokens.TIMES(!pos, !pos));
"("	=> (Tokens.LPAREN(!pos, !pos));
")"	=> (Tokens.RPAREN(!pos, !pos));
"<"     => (Tokens.LANGLE(!pos, !pos));
">"     => (Tokens.RANGLE(!pos, !pos));
"["     => (Tokens.LBRACK(!pos, !pos));
"]"     => (Tokens.RBRACK(!pos, !pos));
"nil?"  => (Tokens.NIL(!pos,!pos));
"hd"    => (Tokens.HEAD(!pos,!pos));
"tl"    => (Tokens.TAIL(!pos,!pos));
"cons"  => (Tokens.CONS(!pos,!pos));
"zero?"	=> (Tokens.ZERO(!pos, !pos));
"and"   => (Tokens.AND(!pos, !pos));
"or"    => (Tokens.OR(!pos, !pos));
"#t"    => (Tokens.TRUE(!pos, !pos));
"#f"    => (Tokens.FALSE(!pos, !pos));
"fn"    => (Tokens.FN(!pos, !pos));
"if"    => (Tokens.IF(!pos, !pos));
"case"  => (Tokens.CASE(!pos,!pos));
"left"  => (Tokens.LEFT(!pos,!pos));
"right" => (Tokens.RIGHT(!pos,!pos));
"fst"   => (Tokens.FST(!pos,!pos));
"snd"   => (Tokens.SND(!pos,!pos));
"letrec"=> (Tokens.LETREC(!pos, !pos));
","     => (Tokens.COMMA(!pos,!pos));

{alpha}+ => (Tokens.VAR(yytext, !pos, !pos));
-?{digit}+ => (case (Int.fromString yytext) of NONE => (error "Bad integer")
	          | SOME n => (Tokens.INT(n, !pos, !pos)));
.	=> (error ("Invalid character found during lexing: " ^ (string_to_cstring yytext)));

