Commit aea46dcd7e

Vexu <git@vexu.eu>
2019-12-28 21:32:18
translate-c-2 macro conditional operator
1 parent 68aa221
Changed files (3)
src-self-hosted/c_tokenizer.zig
@@ -31,6 +31,8 @@ pub const CToken = struct {
         LBrace,
         RBrace,
         Pipe,
+        QuestionMark,
+        Colon,
     };
 
     pub const NumLitSuffix = enum {
@@ -365,6 +367,14 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
                         result.id = .Pipe;
                         state = .Done;
                     },
+                    '?' => {
+                        result.id = .QuestionMark;
+                        state = .Done;
+                    },
+                    ':' => {
+                        result.id = .Colon;
+                        state = .Done;
+                    },
                     else => return error.TokenizingFailed,
                 }
             },
src-self-hosted/translate_c.zig
@@ -4545,6 +4545,18 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
                 call_node.rtoken = try appendToken(rp.c, .RParen, ")");
                 node = &call_node.base;
             },
+            .QuestionMark => {
+                // must come immediately after expr
+                _ = try appendToken(rp.c, .RParen, ")");
+                const if_node = try transCreateNodeIf(rp.c);
+                if_node.condition = node;
+                if_node.body = try parseCPrimaryExpr(rp, it, source_loc, scope);
+                if (it.next().?.id != .Colon)
+                    return error.ParseError;
+                if_node.@"else" = try transCreateNodeElse(rp.c);
+                if_node.@"else".?.body = try parseCPrimaryExpr(rp, it, source_loc, scope);
+                node = &if_node.base;
+            },
             else => {
                 _ = it.prev();
                 return node;
test/translate_c.zig
@@ -2192,6 +2192,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.add_2("macro conditional operator",
+        \\#define FOO a ? b : c
+    , &[_][]const u8{
+        \\pub const FOO = if (a) b else c;
+    });
+
     /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
     cases.addC("Parameterless function prototypes",
         \\void foo() {}