Alex Gaynor avatar Alex Gaynor committed 78422a4

Parser finished.

Comments (0)

Files changed (3)

minijs/grammar.txt

 
 main: statement* [EOF];
 
-statement: expr ";";
+statement: expr ";" |
+           "if" "(" expr ")" "{" statement* "}" |
+           "while" "(" expr ")" "{" statement* "}";
 
 expr: assignment | comparison;
 
 comparison: additive COMP_OPER comparison | additive;
 additive: multitive ADD_OPER additive | multitive;
 multitive: primary MULT_OPER multitive | primary;
-primary: atom;
+primary: "(" additive ")" | atom;
 atom: FLOAT | NAME;
 
 assignment: NAME "=" expr;
         self.var = var
         self.expr = expr
 
+class If(Node):
+    def __init__(self, cond, body):
+        self.cond = cond
+        self.body = body
+
+class While(Node):
+    def __init__(self, cond, body):
+        self.cnod = cond
+        self.body = body
+
 class BinOp(Node):
     def __init__(self, op, lhs, rhs):
         self.op = op
     def visit_stmt(self, node):
         if node.children[0].symbol == "expr":
             return Stmt(self.visit_expr(node.children[0]))
+
+        info = node.children[0].additional_info
+        if info == "if":
+            return self.visit_if(node)
+        elif info == "while":
+            return self.visit_while(node)
         raise NotImplementedError
 
+    def visit_if(self, node):
+        return If(
+            self.visit_expr(node.children[2]),
+            self.visit_block(node.children[5]),
+        )
+
+    def visit_while(self, node):
+        return While(
+            self.visit_expr(node.children[2]),
+            self.visit_block(node.children[5]),
+        )
+
     def visit_expr(self, node):
         if node.symbol == "expr":
             node = node.children[0]
     def visit_primary(self, node):
         if len(node.children) == 1:
             return self.visit_atom(node.children[0])
+        elif node.children[0].additional_info == "(":
+            return self.visit_expr(node.children[1])
         raise NotImplementedError
 
     def visit_atom(self, node):

tests/test_parser.py

-from minijs.parser import Block, Stmt, Assignment, BinOp, Variable, ConstantFloat
+from minijs.parser import (Block, Stmt, If, While, Assignment, BinOp, Variable,
+    ConstantFloat)
 
 
 class TestParser(object):
     def test_multi_term_expr(self, space):
         assert space.parse("1 - 2 * 3;") == Block([Stmt(BinOp("-", ConstantFloat(1), BinOp("*", ConstantFloat(2), ConstantFloat(3))))])
 
+    def test_parens(self, space):
+        assert space.parse("(1 - 2) * 3;") == Block([Stmt(BinOp("*", BinOp("-", ConstantFloat(1), ConstantFloat(2)), ConstantFloat(3)))])
+
     def test_comparisons(self, space):
         assert space.parse("1 > 2;") == Block([Stmt(BinOp(">", ConstantFloat(1), ConstantFloat(2)))])
 
         assert r == Block([
             Stmt(Assignment("a", ConstantFloat(3))),
             Stmt(BinOp("+", Variable("a"), ConstantFloat(2))),
+        ])
+
+    def test_if(self, space):
+        r = space.parse("""
+        if (2) {
+            a = 4;
+        }
+        """)
+        assert r == Block([
+            If(ConstantFloat(2),
+                Block([
+                    Stmt(Assignment("a", ConstantFloat(4))),
+                ])
+            ),
+        ])
+
+    def test_while(self, space):
+        r = space.parse("""
+        i = 0;
+        while (i < 10) {
+            i = i + 1;
+        }
+        """)
+        assert r == Block([
+            Stmt(Assignment("i", ConstantFloat(0))),
+            While(
+                BinOp("<", Variable("i"), ConstantFloat(10)),
+                Block([
+                    Stmt(Assignment("i", BinOp("+", Variable("i"), ConstantFloat(1))))
+                ])
+            ),
         ])
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.