| author | |
| committer | |
| log | aea46dcd7e8521fc04bc1980a596c748961804ab |
| tree | da122977a3f841ce37da059c98b82f538408d959 |
| parent | 68aa221995208a7471290235a86bd184d0057782 |
| signature |
3 files changed, 28 insertions(+), 0 deletions(-)
src-self-hosted/c_tokenizer.zig+10| ... | @@ -31,6 +31,8 @@ pub const CToken = struct { | ... | @@ -31,6 +31,8 @@ pub const CToken = struct { |
| 31 | LBrace, | 31 | LBrace, |
| 32 | RBrace, | 32 | RBrace, |
| 33 | Pipe, | 33 | Pipe, |
| 34 | QuestionMark, | ||
| 35 | Colon, | ||
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | pub const NumLitSuffix = enum { | 38 | pub const NumLitSuffix = enum { |
| ... | @@ -365,6 +367,14 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken { | ... | @@ -365,6 +367,14 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken { |
| 365 | result.id = .Pipe; | 367 | result.id = .Pipe; |
| 366 | state = .Done; | 368 | state = .Done; |
| 367 | }, | 369 | }, |
| 370 | '?' => { | ||
| 371 | result.id = .QuestionMark; | ||
| 372 | state = .Done; | ||
| 373 | }, | ||
| 374 | ':' => { | ||
| 375 | result.id = .Colon; | ||
| 376 | state = .Done; | ||
| 377 | }, | ||
| 368 | else => return error.TokenizingFailed, | 378 | else => return error.TokenizingFailed, |
| 369 | } | 379 | } |
| 370 | }, | 380 | }, |
src-self-hosted/translate_c.zig+12| ... | @@ -4545,6 +4545,18 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc | ... | @@ -4545,6 +4545,18 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 4545 | call_node.rtoken = try appendToken(rp.c, .RParen, ")"); | 4545 | call_node.rtoken = try appendToken(rp.c, .RParen, ")"); |
| 4546 | node = &call_node.base; | 4546 | node = &call_node.base; |
| 4547 | }, | 4547 | }, |
| 4548 | .QuestionMark => { | ||
| 4549 | // must come immediately after expr | ||
| 4550 | _ = try appendToken(rp.c, .RParen, ")"); | ||
| 4551 | const if_node = try transCreateNodeIf(rp.c); | ||
| 4552 | if_node.condition = node; | ||
| 4553 | if_node.body = try parseCPrimaryExpr(rp, it, source_loc, scope); | ||
| 4554 | if (it.next().?.id != .Colon) | ||
| 4555 | return error.ParseError; | ||
| 4556 | if_node.@"else" = try transCreateNodeElse(rp.c); | ||
| 4557 | if_node.@"else".?.body = try parseCPrimaryExpr(rp, it, source_loc, scope); | ||
| 4558 | node = &if_node.base; | ||
| 4559 | }, | ||
| 4548 | else => { | 4560 | else => { |
| 4549 | _ = it.prev(); | 4561 | _ = it.prev(); |
| 4550 | return node; | 4562 | return node; |
test/translate_c.zig+6| ... | @@ -2192,6 +2192,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -2192,6 +2192,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2192 | \\} | 2192 | \\} |
| 2193 | }); | 2193 | }); |
| 2194 | 2194 | ||
| 2195 | cases.add_2("macro conditional operator", | ||
| 2196 | \\#define FOO a ? b : c | ||
| 2197 | , &[_][]const u8{ | ||
| 2198 | \\pub const FOO = if (a) b else c; | ||
| 2199 | }); | ||
| 2200 | |||
| 2195 | /////////////// Cases for only stage1 because stage2 behavior is better //////////////// | 2201 | /////////////// Cases for only stage1 because stage2 behavior is better //////////////// |
| 2196 | cases.addC("Parameterless function prototypes", | 2202 | cases.addC("Parameterless function prototypes", |
| 2197 | \\void foo() {} | 2203 | \\void foo() {} |