def help_eval(self, s): l = lexer.Lexer(s) p = parser.Parser(l) program = p.parse_program() env = {} funcs = {} try: return evaluator.eval(program, env, funcs) except evaluator.EvaluatedError: print(env) pass
def test_return_statement(self): input = "return 5; return a; return a * b;" l = lexer.Lexer(input) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(type(program), ast.Program) self.assertEqual(len(program.statements), 3) for stmt in program.statements: self.assertEqual(type(stmt), ast.ReturnStatement) self.assertEqual(stmt.token_literal(), "return")
def lexer_main(): print("Let's go!!!") print(PROMPT, end='') line = input() while line != "": lex = lexer.Lexer(line) tok = lex.next_token() while tok.type != token.EOF: print(f"<type: {tok.type}, literal: {tok.literal}>") tok = lex.next_token() print(PROMPT, end='') line = input()
def test_prefix_expression(self): input = "-5;" l = lexer.Lexer(input) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) self.assertEqual(type(program.statements[0]), ast.ExpressionStatement) self.assertEqual(type(program.statements[0].expression), ast.PrefixExpression) prefix = program.statements[0].expression self.help_test_integer_literal(prefix.right, 5) self.assertEqual(prefix.operator, "-")
def test_integer_literal_expression(self): input = "5;" l = lexer.Lexer(input) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) self.assertEqual(type(program.statements[0]), ast.ExpressionStatement) self.assertEqual(type(program.statements[0].expression), ast.IntegerLiteral) ident = program.statements[0].expression self.assertEqual(ident.value, 5) self.assertEqual(ident.token_literal(), "5")
def test_return_completion(self): tests = [["return a * b * 3;", ast.InfixExpression], ["return add(3);", ast.CallExpression]] for tt in tests: l = lexer.Lexer(tt[0]) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) self.assertEqual(type(program.statements[0]), ast.ReturnStatement) stmt = program.statements[0] exp = stmt.return_value self.assertEqual(type(exp), tt[1])
def test_function_define(self): tests = [["def a(abc, abc, def) {a + b + c;}", 3], ["def abcde() { return a + b; }", 0]] for i, tt in enumerate(tests): l = lexer.Lexer(tt[0]) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) stmt = program.statements[0] self.assertEqual(type(stmt), ast.FunctionStatement) self.assertEqual(type(stmt.id), ast.Identifier) self.assertEqual(type(stmt.block), ast.BlockStatement) self.help_test_function(stmt, tt[1])
def test_operator_precedence(self): tests = [["-a * b", "((-a) * b)"], ["a + b + c", "((a + b) + c)"], ["-a - b - c", "(((-a) - b) - c)"], ["a / b / c", "((a / b) / c)"], [" a + b * c / d - e", "((a + ((b * c) / d)) - e)"]] for tt in tests: l = lexer.Lexer(tt[0]) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) self.assertEqual(type(program.statements[0]), ast.ExpressionStatement) self.assertEqual(str(program.statements[0]), tt[1])
def file_main(f): res = None env = {} funcs = {} lex = lexer.Lexer(f.read()) par = parser.Parser(lex) program = par.parse_program() if len(par.errors) != 0: for msg in par.errors: print(msg, file=sys.stderr) try: res = evaluator.eval(program, env, funcs) print(res.inspect()) except evaluator.EvaluatedError as e: print(e.msg, file=sys.stderr)
def test_next_token2(self): input = "five = 5; ten = 10; def add(a, b, c) { return a + b + c }; result = add(five, ten, ten);" tests = [ [token.ID, "five"], [token.ASSIGN, "="], [token.INT, "5"], [token.SEMICOLON, ";"], [token.ID, "ten"], [token.ASSIGN, "="], [token.INT, "10"], [token.SEMICOLON, ";"], [token.FUNCTION, "def"], [token.ID, "add"], [token.LPAREN, "("], [token.ID, "a"], [token.COMMA, ","], [token.ID, "b"], [token.COMMA, ","], [token.ID, "c"], [token.RPAREN, ")"], [token.LBRACE, "{"], [token.RETURN, "return"], [token.ID, "a"], [token.PLUS, "+"], [token.ID, "b"], [token.PLUS, "+"], [token.ID, "c"], [token.RBRACE, "}"], [token.SEMICOLON, ";"], [token.ID, "result"], [token.ASSIGN, "="], [token.ID, "add"], [token.LPAREN, "("], [token.ID, "five"], [token.COMMA, ","], [token.ID, "ten"], [token.COMMA, ","], [token.ID, "ten"], [token.RPAREN, ")"], [token.SEMICOLON, ";"], [token.EOF, ""] ] l = lexer.Lexer(input) for i, tt in enumerate(tests): tok = l.next_token() self.assertEqual(tok.type, tt[0], f"{i} test is error") self.assertEqual(tok.literal, tt[1])
def test_assign_statement(self): input = "a = 5; b = 5; c = 10;" l = lexer.Lexer(input) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(type(program), ast.Program) self.assertEqual(len(program.statements), 3) tests = [ "a", "b", "c", ] for i, tt in enumerate(tests): stmt = program.statements[i] self.help_test_assign_statement(stmt, tt[0], i)
def parser_main(): print("Let's go!!!") print(PROMPT, end='') line = input() while line != "": lex = lexer.Lexer(line) par = parser.Parser(lex) program = par.parse_program() if len(par.errors) != 0: for msg in par.errors: print(msg) print(PROMPT, end='') line = input() continue print(str(program)) print(PROMPT, end='') line = input()
def test_infix_expression(self): tests = [["7 + 5;", 7, "+", 5], ["7 - 5;", 7, "-", 5], ["7 * 5;", 7, "*", 5], ["7 / 5;", 7, "/", 5]] for tt in tests: l = lexer.Lexer(tt[0]) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) self.assertEqual(type(program.statements[0]), ast.ExpressionStatement) self.assertEqual(type(program.statements[0].expression), ast.InfixExpression) infix = program.statements[0].expression self.assertEqual(infix.operator, tt[2]) self.help_test_integer_literal(infix.right, tt[3]) self.help_test_integer_literal(infix.left, tt[1])
def test_call_expression(self): tests = [["add(1, 2, 3);", 3], ["add(1+2, 2/3);", 2]] for tt in tests: l = lexer.Lexer(tt[0]) p = parser.Parser(l) program = p.parse_program() self.check_parser_errors(p) self.assertEqual(len(program.statements), 1) self.assertEqual(type(program.statements[0]), ast.ExpressionStatement) stmt = program.statements[0] exp = stmt.expression self.assertEqual(type(exp), ast.CallExpression) self.assertEqual(type(exp.function), ast.Identifier) self.assertEqual(len(exp.arguments), tt[1]) if tt[1] != 0: self.assertTrue( isinstance(exp.arguments[0], ast.ExpressionNode))
def test_next_token1(self): input = "=+-*/(){},;" tests = [ [token.ASSIGN, "="], [token.PLUS, "+"], [token.MINUS, "-"], [token.ASTER, "*"], [token.SLASH, "/"], [token.LPAREN, "("], [token.RPAREN, ")"], [token.LBRACE, "{"], [token.RBRACE, "}"], [token.COMMA, ","], [token.SEMICOLON, ";"], [token.EOF, ""] ] l = lexer.Lexer(input) for i, tt in enumerate(tests): tok = l.next_token() self.assertEqual(tok.type, tt[0]) self.assertEqual(tok.literal, tt[1])
def eval_main(): print("Let's go!!!") print(PROMPT, end='') line = input() env = {} funcs = {} while line != "": lex = lexer.Lexer(line) par = parser.Parser(lex) program = par.parse_program() if len(par.errors) != 0: for msg in par.errors: print(msg) print(PROMPT, end='') line = input() continue try: res = evaluator.eval(program, env, funcs) print(res.inspect()) except evaluator.EvaluatedError as e: print(e.msg) print(PROMPT, end='') line = input()