diff --git a/main.py b/main.py index ae3e5c3..1d0bfa7 100755 --- a/main.py +++ b/main.py @@ -84,8 +84,8 @@ next_line = code.find('\n') + 1 code = code[next_line:] tokens = parse.tokenize(code) - parse.parser_reset(tokens) - ast = parse.parse_file() + parser = parse.Parser(tokens) + ast = parser.parse_file() if not ast: return 1 env = { diff --git a/parse.py b/parse.py index f14d574..a9573e2 100644 --- a/parse.py +++ b/parse.py @@ -39,175 +39,167 @@ tokens.append(('EOF', None)) return tokens -parser_tokens = None -parser_pos = 0 +class Parser: + def __init__(self, tokens): + self.tokens = tokens + self.pos = 0 -def parser_reset(tokens): - global parser_pos - global parser_tokens - parser_tokens = tokens - parser_pos = 0 + def next(self): + (type, value) = self.tokens[self.pos] + if self.pos < (len(self.tokens) - 1): + self.pos += 1 + print("Read %s %s" % (type, value)) + return (type, value) -def parser_next(): - global parser_pos - global parser_tokens - (type, value) = parser_tokens[parser_pos] - if parser_pos < (len(parser_tokens) - 1): - parser_pos += 1 - print("Read %s %s" % (type, value)) - return (type, value) + def peek(self): + (type, value) = self.tokens[self.pos] + print("Peeked %s %s" % (type, value)) + return (type, value) -def parser_peek(): - global parser_pos - global parser_tokens - (type, value) = parser_tokens[parser_pos] - print("Peeked %s %s" % (type, value)) - return (type, value) + def parse_version(self): + (type, value) = self.next() + if type != "keyword" or value != "newlang": + print("Expected NewLang keyword") + return None + (type, value) = self.next() + print("Parsed language version %s" % (value)) + return value -def parse_version(): - (type, value) = parser_next() - if type != "keyword" or value != "newlang": - print("Expected NewLang keyword") - return None - (type, value) = parser_next() - print("Parsed language version %s" % (value)) - return value + def parse_value(self, type, value): + if type == "symbol": + return ('reference', value) + elif type == "text": + return ('text', value) + else: + print("Unexpected type %s" % (type)) + return None -def parse_value(type, value): - if type == "symbol": - return ('reference', value) - elif type == "text": - return ('text', value) - else: - print("Unexpected type %s" % (type)) - return None + def parse_arguments(self, terminator): + args = [] + while True: + (type, value) = self.next() + if type == "keyword": + if value == terminator: + return args + else: + print("Unexpected keyword %s" % (value)) + return None + else: + arg = self.parse_value(type, value) + if not arg: + print("While parsing argument") + return None + args.append(arg) -def parse_arguments(terminator): - args = [] - while True: - (type, value) = parser_next() + def parse_statement(self, terminator): + (type, value) = self.next() + subject = self.parse_value(type, value) + if not subject: + print("While parsing subject") + return None + (type, value) = self.next() if type == "keyword": if value == terminator: - return args + verb = None + else: + print("Unexpected keyword %s" % (value)) + return None + elif type == "symbol": + verb = value + else: + verb = value + if verb: + arguments = self.parse_arguments(terminator) + if arguments is None: + print("While parsing arguments") + return None + else: + arguments = [] + print("Parsed statement: subject %s verb %s args %s" % (subject, verb, arguments)) + return ('statement', subject, verb, arguments) + + def parse_set(self): + (type, value) = self.next() + if type != "symbol": + print("Expect symbol, got %s" % (type)) + return None + subject = value + (type, value) = self.next() + if type != "keyword" or value != "to": + print("Expected To, got %s %s" % (type, value)) + return None + print("Parsing set value...") + ast = self.parse_statement("endset") + if not ast: + print("While parsing statement") + return None + print("Parsed set for %s" % (subject)) + return ('set', subject, ast) + + def parse_if(self): + print("Parsing if test condition...") + test = self.parse_statement("then") + if not test: + print("While parsing test condition") + return None + print("Parsing if success statement...") + success = self.parse_statement("else") + if not success: + print("While parsing success statement") + return None + print("Parsing if failure statement...") + failure = self.parse_statement("endif") + if not failure: + print("While parsing failure statement") + return None + print("Parsed conditional") + return ('if', test, success, failure) + + def parse_directive(self): + (type, value) = self.peek() + if type != "keyword" and type != "symbol": + print("Expected keyword or symbol here, got %s" % (type)) + return None + if type == "keyword": + self.next() + if value == "set": + ast = self.parse_set() + if not ast: + print("While parsing set directive") + return None + return ast + elif value == "if": + ast = self.parse_if() + if not ast: + print("While parsing set directive") + return None + return ast else: print("Unexpected keyword %s" % (value)) return None else: - arg = parse_value(type, value) - if not arg: - print("While parsing argument") - return None - args.append(arg) - -def parse_statement(terminator): - (type, value) = parser_next() - subject = parse_value(type, value) - if not subject: - print("While parsing subject") - return None - (type, value) = parser_next() - if type == "keyword": - if value == terminator: - verb = None - else: - print("Unexpected keyword %s" % (value)) - return None - elif type == "symbol": - verb = value - else: - verb = value - if verb: - arguments = parse_arguments(terminator) - if arguments is None: - print("While parsing arguments") - return None - else: - arguments = [] - print("Parsed statement: subject %s verb %s args %s" % (subject, verb, arguments)) - return ('statement', subject, verb, arguments) - -def parse_set(): - (type, value) = parser_next() - if type != "symbol": - print("Expect symbol, got %s" % (type)) - return None - subject = value - (type, value) = parser_next() - if type != "keyword" or value != "to": - print("Expected To, got %s %s" % (type, value)) - return None - print("Parsing set value...") - ast = parse_statement("endset") - if not ast: - print("While parsing statement") - return None - print("Parsed set for %s" % (subject)) - return ('set', subject, ast) - -def parse_if(): - print("Parsing if test condition...") - test = parse_statement("then") - if not test: - print("While parsing test condition") - return None - print("Parsing if success statement...") - success = parse_statement("else") - if not success: - print("While parsing success statement") - return None - print("Parsing if failure statement...") - failure = parse_statement("endif") - if not failure: - print("While parsing failure statement") - return None - print("Parsed conditional") - return ('if', test, success, failure) - -def parse_directive(): - (type, value) = parser_peek() - if type != "keyword" and type != "symbol": - print("Expected keyword or symbol here, got %s" % (type)) - return None - if type == "keyword": - parser_next() - if value == "set": - ast = parse_set() + ast = self.parse_statement("done") if not ast: - print("While parsing set directive") + print("While parsing statement") return None return ast - elif value == "if": - ast = parse_if() - if not ast: - print("While parsing set directive") + + def parse_file(self): + print("Parsing file...") + ast = [] + version = self.parse_version() + if not version: + print("While parsing version identifier at start of file") + return None + if version != "0": + print("Invalid version identifier %s" % (version)) + return None + while self.peek()[0] != 'EOF': + directive = self.parse_directive() + if directive == None: + print("While parsing directive in file") return None - return ast - else: - print("Unexpected keyword %s" % (value)) - return None - else: - ast = parse_statement("done") - if not ast: - print("While parsing statement") - return None + else: + ast.append(directive) + print("Parsed file") return ast - -def parse_file(): - print("Parsing file...") - ast = [] - version = parse_version() - if not version: - print("While parsing version identifier at start of file") - return None - if version != "0": - print("Invalid version identifier %s" % (version)) - return None - while parser_peek()[0] != 'EOF': - directive = parse_directive() - if directive == None: - print("While parsing directive in file") - return None - else: - ast.append(directive) - print("Parsed file") - return ast