def test_comparison_expr(self): self.check_good_expression("10 >= 10", AST.BoolTypeNode()) self.check_good_expression("10.0 >= 10", AST.BoolTypeNode()) self.check_good_expression("\"abc\" >= \"def\"", AST.BoolTypeNode()) self.check_bad_expression("true >= false", 0, 1) self.check_bad_expression("true >= 10", 0, 1) self.check_bad_expression("10 >= \"abc\"", 0, 1)
def comparison_expr_node(self, expr_node): left, right = self.get_binop_types(expr_node) valid_types = not (left == AST.BoolTypeNode() or right == AST.BoolTypeNode()) same_types = left == right or left.is_numeric() and right.is_numeric() if not valid_types or not same_types: self.handler.add_binop_error(expr_node, left, right) return AST.BoolTypeNode()
def test_question_parsing(self): def format_question(q, n, var_type): return "\"{}\" {}: {}".format(q, n, var_type) question = "Did you sell a house in 2010?" name = "hasSoldHouse" q_type = AST.BoolTypeNode() q_str = format_question(question, name, "boolean") test_node = AST.QuestionNode(question, name, q_type) self.validate_node(self.q_parser, q_str, test_node) question = "Did you sell a house in 2010?" q_type = AST.IntTypeNode() q_str = format_question(question, name, "integer") test_node = AST.QuestionNode(question, name, q_type) self.validate_node(self.q_parser, q_str, test_node) question = "question?" name = "decimalVar" q_type = AST.DecimalTypeNode() q_str = format_question(question, name, "decimal") test_node = AST.QuestionNode(question, name, q_type) self.validate_node(self.q_parser, q_str, test_node) question_str = "name: \"question?\" boolean " self.check_parse_exception(self.q_parser, question_str, pp.ParseException) question_str = "\"question\" name boolean " self.check_parse_exception(self.q_parser, question_str, pp.ParseException) question_str = "\"question?\" boolean: name" self.check_parse_exception(self.q_parser, question_str, pp.ParseException)
def if_else_node(self, if_else_node): expr_type = if_else_node.condition.accept(self) if not expr_type == AST.BoolTypeNode(): self.handler.add_if_cond_error(if_else_node) if_else_node.if_block.accept(self) if_else_node.else_block.accept(self)
def comparison_expr_node(self, expr_node): """ Default behavior for comparison binOps. """ left, right = self.get_binop_types(expr_node) valid_types = not (left.is_boolean() or right.is_boolean()) same_types = left == right or left.is_numeric() and right.is_numeric() if not valid_types or not same_types: self.handler.add_binop_error(expr_node, left, right) return AST.BoolTypeNode()
def test_conditionalIfElse(self): if_expr = AST.VarNode("var") if_block_question = AST.QuestionNode("q?", "var", AST.BoolTypeNode()) if_block = AST.BlockNode([if_block_question]) if_else_cond = AST.IfElseNode(if_expr, if_block, if_block) parse_str = 'if (var) { "q?" var : boolean } else { "q?" var : boolean}' self.validate_node(self.cond_parser, parse_str, if_else_cond) self.check_parse_exception(self.cond_parser, 'if (var) {', pp.ParseException)
def test_computed_questions(self): def format_question(q, n, var_type, expr): return "\"{}\" {}: {} = ({})".format(q, n, var_type, expr) question = "Did you sell a house in 2010?" name = "hasSoldHouse" q_type = AST.BoolTypeNode() q_expr = "-var >= 600" node_expr = AST.GTENode(AST.MinNode(AST.VarNode("var")), AST.IntNode(int("600"))) q_str = format_question(question, name, "boolean", q_expr) test_node = AST.ComputedQuestionNode(question, name, q_type, node_expr) self.validate_node(self.q_parser, q_str, test_node)
def test_monop(self): self.check_good_expression("+10", AST.IntTypeNode()) self.check_good_expression("!true", AST.BoolTypeNode()) self.check_bad_expression("+\"example\"", 0, 1) self.check_bad_expression("!\"example\"", 0, 1)
def test_logical_expressions(self): self.check_good_expression("true && false", AST.BoolTypeNode()) self.check_good_expression("true || true", AST.BoolTypeNode()) self.check_bad_expression("true && 10", 0, 1)
def neg_node(self, neg_node): # '!' has different behavior than the other monOps. var_type = self.get_monop_type(neg_node) if not var_type == AST.BoolTypeNode(): self.handler.add_monop_error(neg_node, var_type) return AST.BoolTypeNode()
def bool_node(_): return AST.BoolTypeNode()
def logical_expr_node(self, expr_node): left, right = self.get_binop_types(expr_node) if not (left == AST.BoolTypeNode() and right == AST.BoolTypeNode()): self.handler.add_binop_error(expr_node, left, right) return AST.BoolTypeNode()