enum Keyword { Enum, Struct, Func, If, Else, While, Break, Continue, Do, For, To, In, Match, Case, Assert, Return, Lambda, Import, Type } enum OptionalKeyword { Some(Keyword), None } func keyword_from_str(keyword: str) -> OptionalKeyword { if keyword == "enum" return OptionalKeyword.Some(Keyword.Enum); if keyword == "struct" return OptionalKeyword.Some(Keyword.Struct); if keyword == "func" return OptionalKeyword.Some(Keyword.Func); if keyword == "if" return OptionalKeyword.Some(Keyword.If); if keyword == "else" return OptionalKeyword.Some(Keyword.Else); if keyword == "while" return OptionalKeyword.Some(Keyword.While); if keyword == "break" return OptionalKeyword.Some(Keyword.Break); if keyword == "continue" return OptionalKeyword.Some(Keyword.Continue); if keyword == "do" return OptionalKeyword.Some(Keyword.Do); if keyword == "for" return OptionalKeyword.Some(Keyword.For); if keyword == "to" return OptionalKeyword.Some(Keyword.To); if keyword == "in" return OptionalKeyword.Some(Keyword.In); if keyword == "match" return OptionalKeyword.Some(Keyword.Match); if keyword == "case" return OptionalKeyword.Some(Keyword.Case); if keyword == "assert" return OptionalKeyword.Some(Keyword.Assert); if keyword == "return" return OptionalKeyword.Some(Keyword.Return); if keyword == "lambda" return OptionalKeyword.Some(Keyword.Lambda); if keyword == "import" return OptionalKeyword.Some(Keyword.Import); if keyword == "type" return OptionalKeyword.Some(Keyword.Type); return OptionalKeyword.None; } func keyword_to_str(keyword: Keyword) -> str { match keyword in { case Enum return "enum"; case Struct return "struct"; case Func return "func"; case If return "if"; case Else return "else"; case While return "while"; case Break return "break"; case Continue return "continue"; case Do return "do"; case For return "for"; case To return "to"; case In return "in"; case Match return "match"; case Case return "case"; case Assert return "assert"; case Return return "return"; case Lambda return "lambda"; case Import return "import"; case Type return "type"; } assert false, "Invalid keyword"; } enum Symbol { Open, Close, OpenCurly, CloseCurly, Comma, OpenSquare, CloseSquare, Colon, Left, Right, Arrow, Semicolon, Equal, Dequal, Exclamation, NotEqual, Dot, Plus, Dash, Asterisk, Dasterisk, Slash, QuestionMark, Ampersand, Dampersand, Pipe, Dpipe, Dleft, Dright, GreaterEqual, LesserEqual, Percent, Tilde, Carot } enum OptionalSymbol { Some(Symbol), None } func symbol_from_str(symbol: str) -> OptionalSymbol { if symbol == "(" return OptionalSymbol.Some(Symbol.Open); if symbol == ")" return OptionalSymbol.Some(Symbol.Close); if symbol == "{" return OptionalSymbol.Some(Symbol.OpenCurly); if symbol == "}" return OptionalSymbol.Some(Symbol.CloseCurly); if symbol == "," return OptionalSymbol.Some(Symbol.Comma); if symbol == "[" return OptionalSymbol.Some(Symbol.OpenSquare); if symbol == "]" return OptionalSymbol.Some(Symbol.CloseSquare); if symbol == ":" return OptionalSymbol.Some(Symbol.Colon); if symbol == "<" return OptionalSymbol.Some(Symbol.Left); if symbol == ">" return OptionalSymbol.Some(Symbol.Right); if symbol == "->" return OptionalSymbol.Some(Symbol.Arrow); if symbol == ";" return OptionalSymbol.Some(Symbol.Semicolon); if symbol == "=" return OptionalSymbol.Some(Symbol.Equal); if symbol == "==" return OptionalSymbol.Some(Symbol.Dequal); if symbol == "!" return OptionalSymbol.Some(Symbol.Exclamation); if symbol == "!=" return OptionalSymbol.Some(Symbol.NotEqual); if symbol == "." return OptionalSymbol.Some(Symbol.Dot); if symbol == "+" return OptionalSymbol.Some(Symbol.Plus); if symbol == "-" return OptionalSymbol.Some(Symbol.Dash); if symbol == "*" return OptionalSymbol.Some(Symbol.Asterisk); if symbol == "**" return OptionalSymbol.Some(Symbol.Dasterisk); if symbol == "/" return OptionalSymbol.Some(Symbol.Slash); if symbol == "?" return OptionalSymbol.Some(Symbol.QuestionMark); if symbol == "&" return OptionalSymbol.Some(Symbol.Ampersand); if symbol == "&&" return OptionalSymbol.Some(Symbol.Dampersand); if symbol == "|" return OptionalSymbol.Some(Symbol.Pipe); if symbol == "||" return OptionalSymbol.Some(Symbol.Dpipe); if symbol == "<<" return OptionalSymbol.Some(Symbol.Dleft); if symbol == ">>" return OptionalSymbol.Some(Symbol.Dright); if symbol == ">=" return OptionalSymbol.Some(Symbol.GreaterEqual); if symbol == "<=" return OptionalSymbol.Some(Symbol.LesserEqual); if symbol == "%" return OptionalSymbol.Some(Symbol.Percent); if symbol == "~" return OptionalSymbol.Some(Symbol.Tilde); if symbol == "^" return OptionalSymbol.Some(Symbol.Carot); assert false, "Unimplemented symbol '%s'" % symbol; } func symbol_to_str(symbol: Symbol) -> str { match symbol in { case Open return "("; case Close return ")"; case OpenCurly return "{"; case CloseCurly return "}"; case Comma return ","; case OpenSquare return "["; case CloseSquare return "]"; case Colon return ":"; case Left return "<"; case Right return ">"; case Arrow return "->"; case Semicolon return ";"; case Equal return "="; case Dequal return "=="; case Exclamation return "!"; case NotEqual return "!="; case Dot return "."; case Plus return "+"; case Dash return "-"; case Asterisk return "*"; case Dasterisk return "**"; case Slash return "/"; case QuestionMark return "?"; case Ampersand return "&"; case Dampersand return "&&"; case Pipe return "|"; case Dpipe return "||"; case Dleft return "<<"; case Dright return ">>"; case GreaterEqual return ">="; case LesserEqual return "<="; case Percent return "%"; case Tilde return "~"; case Carot return "^"; } assert false, "Invalid symbol"; } enum TokenContents { Keyword(Keyword), Identifier(str), Number(int), String(str), Symbol(Symbol), Eof } func token_contents_to_str(token: TokenContents) -> str { match token in { case Keyword(keyword) return "Keyword(%s)" % keyword_to_str(keyword); case Identifier(string) return "Identifier(%s)" % string; case Number(number) return "Number(%d)" % number; case String(string) return "String(\"%s\")" % string; case Symbol(symbol) return "Symbol('%s')" % symbol_to_str(symbol); case Eof return "Eof"; } } struct Token { line: int, col: int, value: str, contents: TokenContents } func token_to_str(token: Token) -> str { return token_contents_to_str(token.contents)+":"+int_to_str(token.line)+":"+int_to_str(token.col); } enum OptionalToken { Some(Token), None } func is_some_token(maybe_token: OptionalToken) -> bool { match maybe_token in { case Some(_) return true; case None return false; } }