{
open System
open FSharp.Text.Lexing
open Parser

let lexeme lexbuf = LexBuffer<_>.LexemeString lexbuf
let newline (lexbuf: LexBuffer<_>) = lexbuf.EndPos <- lexbuf.EndPos.NextLine

}

let whitespace = [' ' '\t']
let newline = ('\n' | '\r' '\n')
let digit = ['0'-'9']
let int = ['-']?digit+
let string = "\"" [^'"']* "\""

let idbody = ['A'-'Z' 'a'-'z' '0'-'9' '_']*
let Uid = ['A'-'Z' '_'] idbody
let Lid = ['a'-'z' '_'] idbody
let id = Uid | Lid

rule linecomment = parse
| newline           { newline lexbuf; tokenstream lexbuf }
| _                 { linecomment lexbuf }

and tokenstream = parse
| whitespace        { tokenstream lexbuf }
| newline           { newline lexbuf; tokenstream lexbuf }
| "//"              { linecomment lexbuf }
| ';'               { SEMICOLON }
| "skip"            { SKIP }
| "if"              { IF }
| "else"            { ELSE }
| "while"           { WHILE }
| "var"             { VAR }
| '='               { ASS }

// Arithmetic operators
| '+'               { PLUS }
| '-'               { MINUS }
| '*'               { MULT }
| '/'               { DIV }

// Boolean operators and comparison operators.
| "true"            { TRUE }
| "false"           { FALSE }
| '!'               { NOT }
| "&&"              { AND }
| "||"              { OR }
| '<'               { LT }
| "<="              { LEQ }
| "=="              { EQ }
| ">="              { GEQ }
| '>'               { GT }
| "!="              { NEQ }

| '('               { LPAREN }
| ')'               { RPAREN }
| '{'               { LCURLPAREN }
| '}'               { RCURLPAREN }

// literals
| int               { Number (Int32.Parse(lexeme lexbuf)) }


// identifiers
| id                { Identifier (lexeme lexbuf) }

| eof               { EOF }
| _                 { lexeme lexbuf |> sprintf "Parsing error: %s" |> failwith }
