Commit 24071c6803

Jimmi Holst Christensen <jimmiholstchristensen@gmail.com>
2018-03-30 21:45:42
std.zig.parser parses all prefix operators
1 parent 1dfa927
Changed files (3)
std/zig/ast.zig
@@ -432,9 +432,15 @@ pub const NodePrefixOp = struct {
     rhs: &Node,
 
     const PrefixOp = union(enum) {
+        AddrOf: AddrOfInfo,
+        BitNot,
+        BoolNot,
+        Deref,
+        Negation,
+        NegationWrap,
         Return,
         Try,
-        AddrOf: AddrOfInfo,
+        UnwrapMaybe,
     };
     const AddrOfInfo = struct {
         align_expr: ?&Node,
@@ -448,14 +454,20 @@ pub const NodePrefixOp = struct {
         var i = index;
 
         switch (self.op) {
-            PrefixOp.Return,
-            PrefixOp.Try => {},
             PrefixOp.AddrOf => |addr_of_info| {
                 if (addr_of_info.align_expr) |align_expr| {
                     if (i < 1) return align_expr;
                     i -= 1;
                 }
             },
+            PrefixOp.BitNot,
+            PrefixOp.BoolNot,
+            PrefixOp.Deref,
+            PrefixOp.Negation,
+            PrefixOp.NegationWrap,
+            PrefixOp.Return,
+            PrefixOp.Try,
+            PrefixOp.UnwrapMaybe => {},
         }
 
         if (i < 1) return self.rhs;
std/zig/parser.zig
@@ -336,6 +336,42 @@ pub const Parser = struct {
                             try stack.append(State.ExpectOperand);
                             continue;
                         },
+                        Token.Id.Minus => {
+                            try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
+                                ast.NodePrefixOp.PrefixOp.Negation) });
+                            try stack.append(State.ExpectOperand);
+                            continue;
+                        },
+                        Token.Id.MinusPercent => {
+                            try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
+                                ast.NodePrefixOp.PrefixOp.NegationWrap) });
+                            try stack.append(State.ExpectOperand);
+                            continue;
+                        },
+                        Token.Id.Tilde => {
+                            try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
+                                ast.NodePrefixOp.PrefixOp.BitNot) });
+                            try stack.append(State.ExpectOperand);
+                            continue;
+                        },
+                        Token.Id.QuestionMarkQuestionMark => {
+                            try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
+                                ast.NodePrefixOp.PrefixOp.UnwrapMaybe) });
+                            try stack.append(State.ExpectOperand);
+                            continue;
+                        },
+                        Token.Id.Bang => {
+                            try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
+                                ast.NodePrefixOp.PrefixOp.BoolNot) });
+                            try stack.append(State.ExpectOperand);
+                            continue;
+                        },
+                        Token.Id.Asterisk => {
+                            try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
+                                ast.NodePrefixOp.PrefixOp.Deref) });
+                            try stack.append(State.ExpectOperand);
+                            continue;
+                        },
                         Token.Id.Ampersand => {
                             const prefix_op = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp{
                                 .AddrOf = ast.NodePrefixOp.AddrOfInfo {
@@ -1323,12 +1359,6 @@ pub const Parser = struct {
                         const prefix_op_node = @fieldParentPtr(ast.NodePrefixOp, "base", base);
                         try stack.append(RenderState { .Expression = prefix_op_node.rhs });
                         switch (prefix_op_node.op) {
-                            ast.NodePrefixOp.PrefixOp.Return => {
-                                try stream.write("return ");
-                            },
-                            ast.NodePrefixOp.PrefixOp.Try => {
-                                try stream.write("try ");
-                            },
                             ast.NodePrefixOp.PrefixOp.AddrOf => |addr_of_info| {
                                 try stream.write("&");
                                 if (addr_of_info.volatile_token != null) {
@@ -1343,6 +1373,14 @@ pub const Parser = struct {
                                     try stack.append(RenderState { .Expression = align_expr});
                                 }
                             },
+                            ast.NodePrefixOp.PrefixOp.BitNot => try stream.write("~"),
+                            ast.NodePrefixOp.PrefixOp.BoolNot => try stream.write("!"),
+                            ast.NodePrefixOp.PrefixOp.Deref => try stream.write("*"),
+                            ast.NodePrefixOp.PrefixOp.Negation => try stream.write("-"),
+                            ast.NodePrefixOp.PrefixOp.NegationWrap => try stream.write("-%"),
+                            ast.NodePrefixOp.PrefixOp.Return => try stream.write("return "),
+                            ast.NodePrefixOp.PrefixOp.Try => try stream.write("try "),
+                            ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"),
                         }
                     },
                     ast.Node.Id.IntegerLiteral => {
@@ -1627,7 +1665,7 @@ test "zig fmt" {
     );
 
     try testCanonical(
-        \\test "operators" {
+        \\test "infix operators" {
         \\    var i = undefined;
         \\    i = 2;
         \\    i *= 2;
@@ -1676,6 +1714,13 @@ test "zig fmt" {
         \\
     );
 
+    try testCanonical(
+        \\test "prefix operators" {
+        \\    --%~??!*&0;
+        \\}
+        \\
+    );
+
     try testCanonical(
         \\test "test calls" {
         \\    a();
std/zig/tokenizer.zig
@@ -125,6 +125,7 @@ pub const Token = struct {
         AngleBracketRightEqual,
         AngleBracketAngleBracketRight,
         AngleBracketAngleBracketRightEqual,
+        Tilde,
         IntegerLiteral,
         FloatLiteral,
         LineComment,
@@ -361,6 +362,11 @@ pub const Tokenizer = struct {
                         self.index += 1;
                         break;
                     },
+                    '~' => {
+                        result.id = Token.Id.Tilde;
+                        self.index += 1;
+                        break;
+                    },
                     '.' => {
                         state = State.Period;
                     },