diff --git a/main.py b/main.py index be4fb71..074b877 100755 --- a/main.py +++ b/main.py @@ -38,6 +38,183 @@ text += symbol return tokens +parser_tokens = None +parser_pos = 0 + +def parser_reset(tokens): + global parser_pos + global parser_tokens + parser_tokens = tokens + parser_pos = 0 + +def parser_eof(): + global parser_pos + global parser_tokens + return parser_pos >= len(parser_tokens) + +def parser_next(): + global parser_pos + global parser_tokens + if parser_eof(): + print("Reached end of file early") + sys.exit(1) + (type, value) = parser_tokens[parser_pos] + parser_pos += 1 + #print("Read %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 parser_skip(): + global parser_pos + global parser_tokens + parser_pos += 1 + +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_subject(): + (type, value) = parser_next() + if type != "symbol": + print("Expected symbol, got %s" % (type)) + return None + return value + +def parse_verb(): + (type, value) = parser_next() + if type != "symbol": + print("Expected symbol, got %s" % (type)) + return None + return value + +def parse_arguments(terminator): + args = [] + while True: + (type, value) = parser_next() + if type == "keyword": + if value == terminator: + return args + else: + print("Unexpected keyword %s" % (value)) + return None + elif type == "text" or type == "symbol": + args.append((type, value)) + else: + print("Unexpected type %s" % (type)) + return None + +def parse_statement(terminator): + subject = parse_subject() + if not subject: + print("While parsing subject") + return None + verb = parse_verb() + if not verb: + print("While parsing verb") + return None + arguments = parse_arguments(terminator) + if arguments is None: + print("While parsing arguments") + return None + print("Parsed statement: subject %s verb %s args %s" % (subject, verb, arguments)) + return ('Statement', subject, verb, arguments) + +def parse_set(): + subject = parse_subject() + if not subject: + print("While parsing subject") + return None + (type, value) = parser_next() + if type != "keyword" or value != "to": + print("Expect 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_skip() + if value == "set": + ast = parse_set() + if not ast: + print("While parsing set directive") + return None + return ast + elif value == "if": + ast = parse_if() + if not ast: + print("While parsing set directive") + 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 + 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 not parser_eof(): + directive = parse_directive() + if directive == None: + print("While parsing directive in file") + return None + else: + ast.append(directive) + print("Parsed file") + return ast + def main(args): if len(args) != 2: print("Usage: main.py FILENAME") @@ -48,8 +225,10 @@ next_line = code.find('\n') + 1 code = code[next_line:] tokens = tokenizer(code) - for t in tokens: - print("TOKEN {0}: {1}".format(t[0], t[1])) + parser_reset(tokens) + ast = parse_file() + if not ast: + return 1 return 0 if __name__ == "__main__":