from sys import stderr KEYWORDS = [ "class", "constructor", "function", "method", "field", "static", "var", "int", "char", "boolean", "void", "true", "false", "null", "this", "let", "do", "if", "else", "while", "return", ] SYMBOLS = "{}()[].,;+-*/&|<>=~" EXIT_CODE_FILE_ERROR = 1 EXIT_CODE_INVALID_TOKEN = 2 EXIT_CODE_SYNTAX_ERROR = 4 EXIT_CODE_EOF = 7 # vim autoindent misbehaves if I type these verbatim in strings LEFT_BRACE = "{" RIGHT_BRACE = "}" LEFT_BRACKET = "[" RIGHT_BRACKET = "]" LEFT_PAREN = "(" RIGHT_PAREN = ")" class JackSyntaxError(Exception): def __init__(self, msg, token): self.message = msg self.token = token super().__init__(msg) class UnexpectedToken(JackSyntaxError): def __init__(self, expected, unexpected): if str(expected) in KEYWORDS or str(expected) in SYMBOLS: # wrap literal keyword/symbol in backticks super().__init__( f"Expected `{expected}`, got `{unexpected}` instead", unexpected ) else: super().__init__( f"Expected {expected}, got `{unexpected}` instead", unexpected ) class Unexpected(JackSyntaxError): def __init__(self, expected, unexpected): super().__init__( f"Expected `{expected}`, got `{unexpected}` instead", unexpected ) def print_err(msg): print(msg, file=stderr)