Beispiel #1
0
 def test_assignment_complex(self):
     parser = Parser()
     tree = parser.run("x = y = 3")
     self.assertEqual(tree.op, Token(lexems.ASSIGNMENT, lexems.ASSIGNMENT))
     self.assertEqual(tree.right.op,
                      Token(lexems.ASSIGNMENT, lexems.ASSIGNMENT))
     self.assertEqual(tree.left.val, Token(lexems.LETTER, 'x'))
Beispiel #2
0
 def test_fn_def_add(self):
     parser = Parser()
     tree = parser.run("fn add x y => x + z")
     self.assertEqual(Token(lexems.LETTER, "add"), tree.name)
     self.assertEqual(
         [Token(lexems.LETTER, "x"),
          Token(lexems.LETTER, "y")], tree.arguments)
     self.assertEqual(Token(lexems.PLUS, lexems.PLUS), tree.definition.op)
Beispiel #3
0
 def test_fn_def(self):
     parser = Parser()
     tree = parser.run("fn avg x y => (x + y) / 2")
     self.assertEqual(Token(lexems.LETTER, "avg"), tree.name)
     self.assertEqual(
         [Token(lexems.LETTER, "x"),
          Token(lexems.LETTER, "y")], tree.arguments)
     self.assertEqual(Token(lexems.DIVIDE, lexems.DIVIDE),
                      tree.definition.op)
Beispiel #4
0
    def test_fn_def_echo_call_no_def(self):
        parser = Parser()
        tree = parser.run("fn echo x => x")
        self.assertEqual(Token(lexems.LETTER, "echo"), tree.name)
        self.assertEqual([Token(lexems.LETTER, "x")], tree.arguments)
        self.assertEqual(Token(lexems.LETTER, "x"), tree.definition.val)

        with self.assertRaises(Exception) as context:
            tree = parser.run("echo1 11")
Beispiel #5
0
 def test_adding(self):
     parser = Parser()
     tree = parser.run("1 + 7")
     self.assertEqual(tree.op, Token(lexems.PLUS, lexems.PLUS))
     self.assertEqual(tree.left.val, Token(lexems.DIGIT, 1))
     self.assertEqual(tree.right.val, Token(lexems.DIGIT, 7))
Beispiel #6
0
 def test_fn_def_echo(self):
     parser = Parser()
     tree = parser.run("fn echo x => x")
     self.assertEqual(Token(lexems.LETTER, "echo"), tree.name)
     self.assertEqual([Token(lexems.LETTER, "x")], tree.arguments)
     self.assertEqual(Token(lexems.LETTER, "x"), tree.definition.val)
Beispiel #7
0
 def test_bad_fn_def(self):
     parser = Parser()
     tree = parser.run("fn avg => (x + y) / 2")
     self.assertEqual(Token(lexems.LETTER, "avg"), tree.name)
Beispiel #8
0
 def test_brackets(self):
     parser = Parser()
     tree = parser.run("(1 + 7) * 5")
     self.assertEqual(tree.op, Token(lexems.MULTIPLY, lexems.MULTIPLY))
     self.assertEqual(tree.right.val, Token(lexems.DIGIT, 5.0))
Beispiel #9
0
 def test_multiply(self):
     parser = Parser()
     tree = parser.run("1 + 7 * 5")
     self.assertEqual(tree.op, Token(lexems.PLUS, lexems.PLUS))
     self.assertEqual(tree.left.val, Token(lexems.DIGIT, 1.0))
Beispiel #10
0
 def test_fn_def_echo_call_no_args(self):
     parser = Parser()
     tree = parser.run("fn echo => 2")
     self.assertEqual(Token(lexems.LETTER, "echo"), tree.name)
Beispiel #11
0
 def __init__(self):
     self.parser = Parser()
     self.variables = {}
     self.functions = {}
Beispiel #12
0
class Interpreter(NodeVisitor):
    def __init__(self):
        self.parser = Parser()
        self.variables = {}
        self.functions = {}

    def input(self, line):
        self.parser.clear()
        tree = self.parser.run(line)
        return self.visit(tree, None)

    def visit_BinaryNode(self, node, var_values, check):
        if check:
            self.visit(node.left, var_values, check)
            self.visit(node.right, var_values, check)
            return None
        if node.op.type == PLUS:
            return self.visit(node.left, var_values) + self.visit(
                node.right, var_values)
        elif node.op.type == MINUS:
            return self.visit(node.left, var_values) - self.visit(
                node.right, var_values)
        elif node.op.type == MULTIPLY:
            return self.visit(node.left, var_values) * self.visit(
                node.right, var_values)
        elif node.op.type == DIVIDE:
            return self.visit(node.left, var_values) / self.visit(
                node.right, var_values)
        elif node.op.type == PERCENT:
            return self.visit(node.left, var_values) % self.visit(
                node.right, var_values)
        elif node.op.type == ASSIGNMENT:
            left = self.visit(node.left, var_values)
            val = self.visit(node.right, var_values)
            self.variables[left] = val
            return val

    def visit_LiteralNode(self, node, var_values, check):
        if node.val.type == LETTER:

            vardict = self.variables
            if var_values != None:
                vardict = var_values

            if node.val.value not in vardict:
                raise Exception("Undefined variable {}".format(node.val.value))
            return vardict[node.val.value]

        if check:
            return None

        if node.val.type == EOF:
            return node.val.value

        return node.val.value

    def visit_VariableDefinitionNode(self, node, var_values, check):
        if node.val.value in self.functions:
            raise Exception("Already defined variable {}".format(
                node.name.value))
        return node.val.value

    def visit_FunctionDefinitionNode(self, node, var_values, check):
        if node.name.value in self.variables:
            raise Exception("Already defined variable {}".format(
                node.name.value))

        self.functions[node.name.value] = node

        # calc parameters
        local_varvalues = {}
        for (i, argnode) in enumerate(node.arguments):
            local_varvalues[argnode.value] = None

        if len(local_varvalues) != len(node.arguments):
            raise Exception("Variable name duplication")

        # check variables
        self.visit(node.definition, local_varvalues, True)
        return ""

    def visit_FunctionCallNode(self, node, var_values, check):
        if node.name.value not in self.functions:
            raise Exception("Undefined function {}".format(node.name.value))
        function_node = self.functions[node.name.value]

        #calc parameters
        local_varvalues = {}
        for (i, argnode) in enumerate(function_node.arguments):
            local_varvalues[argnode.value] = self.visit(
                node.arguments[i], None)

        return self.visit(function_node.definition, local_varvalues)