{ module Lexer open System open FSharp.Text.Lexing open System.Text let keyword (s : string) = match s with | "let" -> Parser.LET | "in" -> Parser.IN | "sum" -> Parser.SUM | "prod" -> Parser.PROD | "max" -> Parser.MAX | "argmax" -> Parser.ARGMAX | "to" -> Parser.TO | "of" -> Parser.OF | _ -> Parser.VAR s } rule Token = parse (* Skip whitespace. *) [' ' '\t' '\r' '\n' ]+ { Token lexbuf } (* Integers. *) | '0' | ['1'-'9']['0'-'9']* { Parser.INT (int (Encoding.UTF8.GetString lexbuf.Lexeme)) } (* Symbols *) | '(' { Parser.LPAR } | ')' { Parser.RPAR } | '=' { Parser.EQ } | '+' { Parser.PLUS } | '-' { Parser.MINUS } | '*' { Parser.TIMES } | ['a'-'z' 'A'-'Z']* ('_' ['a'-'z' 'A'-'Z' '_' '0'-'9']* )? { keyword (Encoding.UTF8.GetString lexbuf.Lexeme) } (* FIXME: You should implement lexing for: (1) Variable names: may contain letters, digits and underscores, but it must start with one (or several) letters, and a digit must be preceeded by an underscore. (2) Keywords: 'let', 'in', 'sum', ... (3) Symbols: '=', '+', ... For (1) and (2), please change the regular expression above to be consistent with the rule defining variable names, and implement the keywords function. For (3), add the relevant regular expressions under 'Symbols' *) (* Special end of file symbol. *) | eof { Parser.EOF } (* We don't understand anything else. *) | _ { failwith "lexer error" }