Commits

Alex Gaynor  committed 8af22c3

variable support in the parser

  • Participants
  • Parent commits bc71a31

Comments (0)

Files changed (3)

File minijs/grammar.txt

 COMP_OPER: "(==)|(>=)|(<=)|>|<|(!=)";
 
 FLOAT: "[0-9]+";
+NAME: "[a-zA-Z_][a-zA-Z0-9_]*";
 
 main: statement* [EOF];
 
 statement: expr ";";
 
-expr: comparison;
+expr: assignment | comparison;
 
 comparison: additive COMP_OPER comparison | additive;
 additive: multitive ADD_OPER additive | multitive;
 multitive: primary MULT_OPER multitive | primary;
 primary: atom;
-atom: FLOAT;
+atom: FLOAT | NAME;
+
+assignment: NAME "=" expr;

File minijs/parser.py

 
 class Block(Node):
     def __init__(self, stmts):
-        self.stmt = stmts
+        self.stmts = stmts
 
 class Stmt(Node):
     def __init__(self, expr):
         self.expr = expr
 
+class Assignment(Node):
+    def __init__(self, var, expr):
+        self.var = var
+        self.expr = expr
+
 class BinOp(Node):
     def __init__(self, op, lhs, rhs):
         self.op = op
         self.lhs = lhs
         self.rhs = rhs
 
+class Variable(Node):
+    def __init__(self, var):
+        self.var = var
+
 class ConstantFloat(Node):
     def __init__(self, floatval):
         self.floatval = floatval
             node = node.children[0]
 
         symname = node.symbol
-        if symname in ["additive", "multitive", "comparison"]:
+        if symname == "assignment":
+            return self.visit_assignment(node)
+        elif symname in ["additive", "multitive", "comparison"]:
             return self.visit_subexpr(node)
         elif symname == "primary":
             return self.visit_primary(node)
         )
         raise NotImplementedError
 
+    def visit_assignment(self, node):
+        return Assignment(
+            node.children[0].additional_info,
+            self.visit_expr(node.children[2])
+        )
+
     def visit_primary(self, node):
         if len(node.children) == 1:
             return self.visit_atom(node.children[0])
         raise NotImplementedError
 
     def visit_atom(self, node):
-        if node.children[0].symbol == "FLOAT":
-            return ConstantFloat(float(node.children[0].additional_info))
+        symname = node.children[0].symbol
+        if symname == "FLOAT":
+            return ConstantFloat(float(node.children[0].additional_info))
+        elif symname == "NAME":
+            return Variable(node.children[0].additional_info)
+        raise NotImplementedError

File tests/test_parser.py

-from minijs.parser import Block, Stmt, BinOp, ConstantFloat
+from minijs.parser import Block, Stmt, Assignment, BinOp, Variable, ConstantFloat
 
 
 class TestParser(object):
     def test_comparisons(self, space):
         assert space.parse("1 > 2;") == Block([Stmt(BinOp(">", ConstantFloat(1), ConstantFloat(2)))])
 
+    def test_multiple_statements(self, space):
+        r = space.parse("""
+        1 + 1;
+        2 + 2;
+        3 + 3;
+        """)
+        assert r == Block([
+            Stmt(BinOp("+", ConstantFloat(1), ConstantFloat(1))),
+            Stmt(BinOp("+", ConstantFloat(2), ConstantFloat(2))),
+            Stmt(BinOp("+", ConstantFloat(3), ConstantFloat(3))),
+        ])
+
+    def test_variables(self, space):
+        r = space.parse("""
+        a = 3;
+        a + 2;
+        """)
+        assert r == Block([
+            Stmt(Assignment("a", ConstantFloat(3))),
+            Stmt(BinOp("+", Variable("a"), ConstantFloat(2))),
+        ])