| ... | ... | @@ -5527,58 +5527,41 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5527 | 5527 | const ParseError = Error || error{ParseError}; |
| 5528 | 5528 | |
| 5529 | 5529 | fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5530 | | const node = try parseCPrefixOpExpr(c, m, scope); |
| 5531 | | switch (m.next().?) { |
| 5532 | | .QuestionMark => { |
| 5533 | | // must come immediately after expr |
| 5534 | | _ = try appendToken(c, .RParen, ")"); |
| 5535 | | const if_node = try transCreateNodeIf(c); |
| 5536 | | if_node.condition = node; |
| 5537 | | if_node.body = try parseCPrimaryExpr(c, m, scope); |
| 5538 | | if (m.next().? != .Colon) { |
| 5539 | | try m.fail(c, "unable to translate C expr: expected ':'", .{}); |
| 5540 | | return error.ParseError; |
| 5541 | | } |
| 5542 | | if_node.@"else" = try transCreateNodeElse(c); |
| 5543 | | if_node.@"else".?.body = try parseCPrimaryExpr(c, m, scope); |
| 5544 | | return &if_node.base; |
| 5545 | | }, |
| 5546 | | .Comma => { |
| 5547 | | _ = try appendToken(c, .Semicolon, ";"); |
| 5548 | | var block_scope = try Scope.Block.init(c, scope, true); |
| 5549 | | defer block_scope.deinit(); |
| 5550 | | |
| 5551 | | var last = node; |
| 5552 | | while (true) { |
| 5553 | | // suppress result |
| 5554 | | const lhs = try transCreateNodeIdentifier(c, "_"); |
| 5555 | | const op_token = try appendToken(c, .Equal, "="); |
| 5556 | | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 5557 | | op_node.* = .{ |
| 5558 | | .base = .{ .tag = .Assign }, |
| 5559 | | .op_token = op_token, |
| 5560 | | .lhs = lhs, |
| 5561 | | .rhs = last, |
| 5562 | | }; |
| 5563 | | try block_scope.statements.append(&op_node.base); |
| 5530 | // TODO parseCAssignExpr here |
| 5531 | const node = try parseCCondExpr(c, m, scope); |
| 5532 | if (m.next().? != .Comma) { |
| 5533 | m.i -= 1; |
| 5534 | return node; |
| 5535 | } |
| 5536 | _ = try appendToken(c, .Semicolon, ";"); |
| 5537 | var block_scope = try Scope.Block.init(c, scope, true); |
| 5538 | defer block_scope.deinit(); |
| 5564 | 5539 | |
| 5565 | | last = try parseCPrefixOpExpr(c, m, scope); |
| 5566 | | _ = try appendToken(c, .Semicolon, ";"); |
| 5567 | | if (m.next().? != .Comma) { |
| 5568 | | m.i -= 1; |
| 5569 | | break; |
| 5570 | | } |
| 5571 | | } |
| 5540 | var last = node; |
| 5541 | while (true) { |
| 5542 | // suppress result |
| 5543 | const lhs = try transCreateNodeIdentifier(c, "_"); |
| 5544 | const op_token = try appendToken(c, .Equal, "="); |
| 5545 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 5546 | op_node.* = .{ |
| 5547 | .base = .{ .tag = .Assign }, |
| 5548 | .op_token = op_token, |
| 5549 | .lhs = lhs, |
| 5550 | .rhs = last, |
| 5551 | }; |
| 5552 | try block_scope.statements.append(&op_node.base); |
| 5572 | 5553 | |
| 5573 | | const break_node = try transCreateNodeBreak(c, block_scope.label, last); |
| 5574 | | try block_scope.statements.append(&break_node.base); |
| 5575 | | return try block_scope.complete(c); |
| 5576 | | }, |
| 5577 | | else => { |
| 5554 | last = try parseCCondExpr(c, m, scope); |
| 5555 | _ = try appendToken(c, .Semicolon, ";"); |
| 5556 | if (m.next().? != .Comma) { |
| 5578 | 5557 | m.i -= 1; |
| 5579 | | return node; |
| 5580 | | }, |
| 5558 | break; |
| 5559 | } |
| 5581 | 5560 | } |
| 5561 | |
| 5562 | const break_node = try transCreateNodeBreak(c, block_scope.label, last); |
| 5563 | try block_scope.statements.append(&break_node.base); |
| 5564 | return try block_scope.complete(c); |
| 5582 | 5565 | } |
| 5583 | 5566 | |
| 5584 | 5567 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { |
| ... | ... | @@ -5805,7 +5788,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5805 | 5788 | return bytes[0..i]; |
| 5806 | 5789 | } |
| 5807 | 5790 | |
| 5808 | | fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5791 | fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5809 | 5792 | const tok = m.next().?; |
| 5810 | 5793 | const slice = m.slice(); |
| 5811 | 5794 | switch (tok) { |
| ... | ... | @@ -5952,6 +5935,30 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N |
| 5952 | 5935 | } |
| 5953 | 5936 | } |
| 5954 | 5937 | |
| 5938 | fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5939 | var node = try parseCPrimaryExprInner(c, m, scope); |
| 5940 | // In C the preprocessor would handle concatting strings while expanding macros. |
| 5941 | // This should do approximately the same by concatting any strings and identifiers |
| 5942 | // after a primary expression. |
| 5943 | while (true) { |
| 5944 | var op_token: ast.TokenIndex = undefined; |
| 5945 | var op_id: ast.Node.Tag = undefined; |
| 5946 | switch (m.peek().?) { |
| 5947 | .StringLiteral, .Identifier => {}, |
| 5948 | else => break, |
| 5949 | } |
| 5950 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 5951 | op_node.* = .{ |
| 5952 | .base = .{ .tag = .ArrayCat }, |
| 5953 | .op_token = try appendToken(c, .PlusPlus, "++"), |
| 5954 | .lhs = node, |
| 5955 | .rhs = try parseCPrimaryExprInner(c, m, scope), |
| 5956 | }; |
| 5957 | node = &op_node.base; |
| 5958 | } |
| 5959 | return node; |
| 5960 | } |
| 5961 | |
| 5955 | 5962 | fn nodeIsInfixOp(tag: ast.Node.Tag) bool { |
| 5956 | 5963 | return switch (tag) { |
| 5957 | 5964 | .Add, |
| ... | ... | @@ -6053,31 +6060,268 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { |
| 6053 | 6060 | return &group_node.base; |
| 6054 | 6061 | } |
| 6055 | 6062 | |
| 6056 | | fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6057 | | var node = try parseCPrimaryExpr(c, m, scope); |
| 6063 | fn macroGroup(c: *Context, node: *ast.Node) !*ast.Node { |
| 6064 | if (!nodeIsInfixOp(node.tag)) return node; |
| 6065 | |
| 6066 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| 6067 | group_node.* = .{ |
| 6068 | .lparen = try appendToken(c, .LParen, "("), |
| 6069 | .expr = node, |
| 6070 | .rparen = try appendToken(c, .RParen, ")"), |
| 6071 | }; |
| 6072 | return &group_node.base; |
| 6073 | } |
| 6074 | |
| 6075 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6076 | const node = try parseCOrExpr(c, m, scope); |
| 6077 | if (m.peek().? != .QuestionMark) { |
| 6078 | return node; |
| 6079 | } |
| 6080 | _ = m.next(); |
| 6081 | |
| 6082 | // must come immediately after expr |
| 6083 | _ = try appendToken(c, .RParen, ")"); |
| 6084 | const if_node = try transCreateNodeIf(c); |
| 6085 | if_node.condition = node; |
| 6086 | if_node.body = try parseCOrExpr(c, m, scope); |
| 6087 | if (m.next().? != .Colon) { |
| 6088 | try m.fail(c, "unable to translate C expr: expected ':'", .{}); |
| 6089 | return error.ParseError; |
| 6090 | } |
| 6091 | if_node.@"else" = try transCreateNodeElse(c); |
| 6092 | if_node.@"else".?.body = try parseCCondExpr(c, m, scope); |
| 6093 | return &if_node.base; |
| 6094 | } |
| 6095 | |
| 6096 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6097 | var node = try parseCAndExpr(c, m, scope); |
| 6098 | while (m.next().? == .PipePipe) { |
| 6099 | const lhs_node = try macroIntToBool(c, node); |
| 6100 | const op_token = try appendToken(c, .Keyword_or, "or"); |
| 6101 | const rhs_node = try parseCAndExpr(c, m, scope); |
| 6102 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6103 | op_node.* = .{ |
| 6104 | .base = .{ .tag = .BoolOr }, |
| 6105 | .op_token = op_token, |
| 6106 | .lhs = lhs_node, |
| 6107 | .rhs = try macroIntToBool(c, rhs_node), |
| 6108 | }; |
| 6109 | node = &op_node.base; |
| 6110 | } |
| 6111 | m.i -= 1; |
| 6112 | return node; |
| 6113 | } |
| 6114 | |
| 6115 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6116 | var node = try parseCBitOrExpr(c, m, scope); |
| 6117 | while (m.next().? == .AmpersandAmpersand) { |
| 6118 | const lhs_node = try macroIntToBool(c, node); |
| 6119 | const op_token = try appendToken(c, .Keyword_and, "and"); |
| 6120 | const rhs_node = try parseCBitOrExpr(c, m, scope); |
| 6121 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6122 | op_node.* = .{ |
| 6123 | .base = .{ .tag = .BoolAnd }, |
| 6124 | .op_token = op_token, |
| 6125 | .lhs = lhs_node, |
| 6126 | .rhs = try macroIntToBool(c, rhs_node), |
| 6127 | }; |
| 6128 | node = &op_node.base; |
| 6129 | } |
| 6130 | m.i -= 1; |
| 6131 | return node; |
| 6132 | } |
| 6133 | |
| 6134 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6135 | var node = try parseCBitXorExpr(c, m, scope); |
| 6136 | while (m.next().? == .Pipe) { |
| 6137 | const lhs_node = try macroBoolToInt(c, node); |
| 6138 | const op_token = try appendToken(c, .Pipe, "|"); |
| 6139 | const rhs_node = try parseCBitXorExpr(c, m, scope); |
| 6140 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6141 | op_node.* = .{ |
| 6142 | .base = .{ .tag = .BitOr }, |
| 6143 | .op_token = op_token, |
| 6144 | .lhs = lhs_node, |
| 6145 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6146 | }; |
| 6147 | node = &op_node.base; |
| 6148 | } |
| 6149 | m.i -= 1; |
| 6150 | return node; |
| 6151 | } |
| 6152 | |
| 6153 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6154 | var node = try parseCBitAndExpr(c, m, scope); |
| 6155 | while (m.next().? == .Caret) { |
| 6156 | const lhs_node = try macroBoolToInt(c, node); |
| 6157 | const op_token = try appendToken(c, .Caret, "^"); |
| 6158 | const rhs_node = try parseCBitAndExpr(c, m, scope); |
| 6159 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6160 | op_node.* = .{ |
| 6161 | .base = .{ .tag = .BitXor }, |
| 6162 | .op_token = op_token, |
| 6163 | .lhs = lhs_node, |
| 6164 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6165 | }; |
| 6166 | node = &op_node.base; |
| 6167 | } |
| 6168 | m.i -= 1; |
| 6169 | return node; |
| 6170 | } |
| 6171 | |
| 6172 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6173 | var node = try parseCEqExpr(c, m, scope); |
| 6174 | while (m.next().? == .Ampersand) { |
| 6175 | const lhs_node = try macroBoolToInt(c, node); |
| 6176 | const op_token = try appendToken(c, .Ampersand, "&"); |
| 6177 | const rhs_node = try parseCEqExpr(c, m, scope); |
| 6178 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6179 | op_node.* = .{ |
| 6180 | .base = .{ .tag = .BitAnd }, |
| 6181 | .op_token = op_token, |
| 6182 | .lhs = lhs_node, |
| 6183 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6184 | }; |
| 6185 | node = &op_node.base; |
| 6186 | } |
| 6187 | m.i -= 1; |
| 6188 | return node; |
| 6189 | } |
| 6190 | |
| 6191 | fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6192 | var node = try parseCRelExpr(c, m, scope); |
| 6058 | 6193 | while (true) { |
| 6059 | 6194 | var op_token: ast.TokenIndex = undefined; |
| 6060 | 6195 | var op_id: ast.Node.Tag = undefined; |
| 6061 | | var bool_op = false; |
| 6062 | | switch (m.next().?) { |
| 6063 | | .Period => { |
| 6064 | | if (m.next().? != .Identifier) { |
| 6065 | | try m.fail(c, "unable to translate C expr: expected identifier", .{}); |
| 6066 | | return error.ParseError; |
| 6067 | | } |
| 6196 | switch (m.peek().?) { |
| 6197 | .BangEqual => { |
| 6198 | op_token = try appendToken(c, .BangEqual, "!="); |
| 6199 | op_id = .BangEqual; |
| 6200 | }, |
| 6201 | .EqualEqual => { |
| 6202 | op_token = try appendToken(c, .EqualEqual, "=="); |
| 6203 | op_id = .EqualEqual; |
| 6204 | }, |
| 6205 | else => return node, |
| 6206 | } |
| 6207 | _ = m.next(); |
| 6208 | const lhs_node = try macroBoolToInt(c, node); |
| 6209 | const rhs_node = try parseCRelExpr(c, m, scope); |
| 6210 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6211 | op_node.* = .{ |
| 6212 | .base = .{ .tag = op_id }, |
| 6213 | .op_token = op_token, |
| 6214 | .lhs = lhs_node, |
| 6215 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6216 | }; |
| 6217 | node = &op_node.base; |
| 6218 | } |
| 6219 | } |
| 6068 | 6220 | |
| 6069 | | node = try transCreateNodeFieldAccess(c, node, m.slice()); |
| 6070 | | continue; |
| 6221 | fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6222 | var node = try parseCShiftExpr(c, m, scope); |
| 6223 | while (true) { |
| 6224 | var op_token: ast.TokenIndex = undefined; |
| 6225 | var op_id: ast.Node.Tag = undefined; |
| 6226 | switch (m.peek().?) { |
| 6227 | .AngleBracketRight => { |
| 6228 | op_token = try appendToken(c, .AngleBracketRight, ">"); |
| 6229 | op_id = .GreaterThan; |
| 6071 | 6230 | }, |
| 6072 | | .Arrow => { |
| 6073 | | if (m.next().? != .Identifier) { |
| 6074 | | try m.fail(c, "unable to translate C expr: expected identifier", .{}); |
| 6075 | | return error.ParseError; |
| 6076 | | } |
| 6077 | | const deref = try transCreateNodePtrDeref(c, node); |
| 6078 | | node = try transCreateNodeFieldAccess(c, deref, m.slice()); |
| 6079 | | continue; |
| 6231 | .AngleBracketRightEqual => { |
| 6232 | op_token = try appendToken(c, .AngleBracketRightEqual, ">="); |
| 6233 | op_id = .GreaterOrEqual; |
| 6234 | }, |
| 6235 | .AngleBracketLeft => { |
| 6236 | op_token = try appendToken(c, .AngleBracketLeft, "<"); |
| 6237 | op_id = .LessThan; |
| 6080 | 6238 | }, |
| 6239 | .AngleBracketLeftEqual => { |
| 6240 | op_token = try appendToken(c, .AngleBracketLeftEqual, "<="); |
| 6241 | op_id = .LessOrEqual; |
| 6242 | }, |
| 6243 | else => return node, |
| 6244 | } |
| 6245 | _ = m.next(); |
| 6246 | const lhs_node = try macroBoolToInt(c, node); |
| 6247 | const rhs_node = try parseCShiftExpr(c, m, scope); |
| 6248 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6249 | op_node.* = .{ |
| 6250 | .base = .{ .tag = op_id }, |
| 6251 | .op_token = op_token, |
| 6252 | .lhs = lhs_node, |
| 6253 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6254 | }; |
| 6255 | node = &op_node.base; |
| 6256 | } |
| 6257 | } |
| 6258 | |
| 6259 | fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6260 | var node = try parseCAddSubExpr(c, m, scope); |
| 6261 | while (true) { |
| 6262 | var op_token: ast.TokenIndex = undefined; |
| 6263 | var op_id: ast.Node.Tag = undefined; |
| 6264 | switch (m.peek().?) { |
| 6265 | .AngleBracketAngleBracketLeft => { |
| 6266 | op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<"); |
| 6267 | op_id = .BitShiftLeft; |
| 6268 | }, |
| 6269 | .AngleBracketAngleBracketRight => { |
| 6270 | op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>"); |
| 6271 | op_id = .BitShiftRight; |
| 6272 | }, |
| 6273 | else => return node, |
| 6274 | } |
| 6275 | _ = m.next(); |
| 6276 | const lhs_node = try macroBoolToInt(c, node); |
| 6277 | const rhs_node = try parseCAddSubExpr(c, m, scope); |
| 6278 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6279 | op_node.* = .{ |
| 6280 | .base = .{ .tag = op_id }, |
| 6281 | .op_token = op_token, |
| 6282 | .lhs = lhs_node, |
| 6283 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6284 | }; |
| 6285 | node = &op_node.base; |
| 6286 | } |
| 6287 | } |
| 6288 | |
| 6289 | fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6290 | var node = try parseCMulExpr(c, m, scope); |
| 6291 | while (true) { |
| 6292 | var op_token: ast.TokenIndex = undefined; |
| 6293 | var op_id: ast.Node.Tag = undefined; |
| 6294 | switch (m.peek().?) { |
| 6295 | .Plus => { |
| 6296 | op_token = try appendToken(c, .Plus, "+"); |
| 6297 | op_id = .Add; |
| 6298 | }, |
| 6299 | .Minus => { |
| 6300 | op_token = try appendToken(c, .Minus, "-"); |
| 6301 | op_id = .Sub; |
| 6302 | }, |
| 6303 | else => return node, |
| 6304 | } |
| 6305 | _ = m.next(); |
| 6306 | const lhs_node = try macroBoolToInt(c, node); |
| 6307 | const rhs_node = try parseCMulExpr(c, m, scope); |
| 6308 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6309 | op_node.* = .{ |
| 6310 | .base = .{ .tag = op_id }, |
| 6311 | .op_token = op_token, |
| 6312 | .lhs = lhs_node, |
| 6313 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6314 | }; |
| 6315 | node = &op_node.base; |
| 6316 | } |
| 6317 | } |
| 6318 | |
| 6319 | fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6320 | var node = try parseCUnaryExpr(c, m, scope); |
| 6321 | while (true) { |
| 6322 | var op_token: ast.TokenIndex = undefined; |
| 6323 | var op_id: ast.Node.Tag = undefined; |
| 6324 | switch (m.next().?) { |
| 6081 | 6325 | .Asterisk => { |
| 6082 | 6326 | if (m.peek().? == .RParen) { |
| 6083 | 6327 | // type *) |
| ... | ... | @@ -6105,59 +6349,57 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6105 | 6349 | op_id = .BitShiftLeft; |
| 6106 | 6350 | } |
| 6107 | 6351 | }, |
| 6108 | | .AngleBracketAngleBracketLeft => { |
| 6109 | | op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<"); |
| 6110 | | op_id = .BitShiftLeft; |
| 6111 | | }, |
| 6112 | | .AngleBracketAngleBracketRight => { |
| 6113 | | op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>"); |
| 6114 | | op_id = .BitShiftRight; |
| 6115 | | }, |
| 6116 | | .Pipe => { |
| 6117 | | op_token = try appendToken(c, .Pipe, "|"); |
| 6118 | | op_id = .BitOr; |
| 6119 | | }, |
| 6120 | | .Ampersand => { |
| 6121 | | op_token = try appendToken(c, .Ampersand, "&"); |
| 6122 | | op_id = .BitAnd; |
| 6123 | | }, |
| 6124 | | .Plus => { |
| 6125 | | op_token = try appendToken(c, .Plus, "+"); |
| 6126 | | op_id = .Add; |
| 6127 | | }, |
| 6128 | | .Minus => { |
| 6129 | | op_token = try appendToken(c, .Minus, "-"); |
| 6130 | | op_id = .Sub; |
| 6131 | | }, |
| 6132 | | .AmpersandAmpersand => { |
| 6133 | | op_token = try appendToken(c, .Keyword_and, "and"); |
| 6134 | | op_id = .BoolAnd; |
| 6135 | | bool_op = true; |
| 6136 | | }, |
| 6137 | | .PipePipe => { |
| 6138 | | op_token = try appendToken(c, .Keyword_or, "or"); |
| 6139 | | op_id = .BoolOr; |
| 6140 | | bool_op = true; |
| 6352 | .Slash => { |
| 6353 | op_id = .Div; |
| 6354 | op_token = try appendToken(c, .Slash, "/"); |
| 6141 | 6355 | }, |
| 6142 | | .AngleBracketRight => { |
| 6143 | | op_token = try appendToken(c, .AngleBracketRight, ">"); |
| 6144 | | op_id = .GreaterThan; |
| 6356 | .Percent => { |
| 6357 | op_id = .Mod; |
| 6358 | op_token = try appendToken(c, .Percent, "%"); |
| 6145 | 6359 | }, |
| 6146 | | .AngleBracketRightEqual => { |
| 6147 | | op_token = try appendToken(c, .AngleBracketRightEqual, ">="); |
| 6148 | | op_id = .GreaterOrEqual; |
| 6360 | else => { |
| 6361 | m.i -= 1; |
| 6362 | return node; |
| 6149 | 6363 | }, |
| 6150 | | .AngleBracketLeft => { |
| 6151 | | op_token = try appendToken(c, .AngleBracketLeft, "<"); |
| 6152 | | op_id = .LessThan; |
| 6364 | } |
| 6365 | const lhs_node = try macroBoolToInt(c, node); |
| 6366 | const rhs_node = try parseCUnaryExpr(c, m, scope); |
| 6367 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6368 | op_node.* = .{ |
| 6369 | .base = .{ .tag = op_id }, |
| 6370 | .op_token = op_token, |
| 6371 | .lhs = lhs_node, |
| 6372 | .rhs = try macroBoolToInt(c, rhs_node), |
| 6373 | }; |
| 6374 | node = &op_node.base; |
| 6375 | } |
| 6376 | } |
| 6377 | |
| 6378 | fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6379 | var node = try parseCPrimaryExpr(c, m, scope); |
| 6380 | while (true) { |
| 6381 | switch (m.next().?) { |
| 6382 | .Period => { |
| 6383 | if (m.next().? != .Identifier) { |
| 6384 | try m.fail(c, "unable to translate C expr: expected identifier", .{}); |
| 6385 | return error.ParseError; |
| 6386 | } |
| 6387 | |
| 6388 | node = try transCreateNodeFieldAccess(c, node, m.slice()); |
| 6389 | continue; |
| 6153 | 6390 | }, |
| 6154 | | .AngleBracketLeftEqual => { |
| 6155 | | op_token = try appendToken(c, .AngleBracketLeftEqual, "<="); |
| 6156 | | op_id = .LessOrEqual; |
| 6391 | .Arrow => { |
| 6392 | if (m.next().? != .Identifier) { |
| 6393 | try m.fail(c, "unable to translate C expr: expected identifier", .{}); |
| 6394 | return error.ParseError; |
| 6395 | } |
| 6396 | const deref = try transCreateNodePtrDeref(c, node); |
| 6397 | node = try transCreateNodeFieldAccess(c, deref, m.slice()); |
| 6398 | continue; |
| 6157 | 6399 | }, |
| 6158 | 6400 | .LBracket => { |
| 6159 | 6401 | const arr_node = try transCreateNodeArrayAccess(c, node); |
| 6160 | | arr_node.index_expr = try parseCPrefixOpExpr(c, m, scope); |
| 6402 | arr_node.index_expr = try parseCExpr(c, m, scope); |
| 6161 | 6403 | arr_node.rtoken = try appendToken(c, .RBracket, "]"); |
| 6162 | 6404 | node = &arr_node.base; |
| 6163 | 6405 | if (m.next().? != .RBracket) { |
| ... | ... | @@ -6171,7 +6413,7 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6171 | 6413 | var call_params = std.ArrayList(*ast.Node).init(c.gpa); |
| 6172 | 6414 | defer call_params.deinit(); |
| 6173 | 6415 | while (true) { |
| 6174 | | const arg = try parseCPrefixOpExpr(c, m, scope); |
| 6416 | const arg = try parseCCondExpr(c, m, scope); |
| 6175 | 6417 | try call_params.append(arg); |
| 6176 | 6418 | switch (m.next().?) { |
| 6177 | 6419 | .Comma => _ = try appendToken(c, .Comma, ","), |
| ... | ... | @@ -6204,7 +6446,7 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6204 | 6446 | defer init_vals.deinit(); |
| 6205 | 6447 | |
| 6206 | 6448 | while (true) { |
| 6207 | | const val = try parseCPrefixOpExpr(c, m, scope); |
| 6449 | const val = try parseCCondExpr(c, m, scope); |
| 6208 | 6450 | try init_vals.append(val); |
| 6209 | 6451 | switch (m.next().?) { |
| 6210 | 6452 | .Comma => _ = try appendToken(c, .Comma, ","), |
| ... | ... | @@ -6239,90 +6481,57 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6239 | 6481 | node = &zero_init_call.base; |
| 6240 | 6482 | continue; |
| 6241 | 6483 | }, |
| 6242 | | .BangEqual => { |
| 6243 | | op_token = try appendToken(c, .BangEqual, "!="); |
| 6244 | | op_id = .BangEqual; |
| 6245 | | }, |
| 6246 | | .EqualEqual => { |
| 6247 | | op_token = try appendToken(c, .EqualEqual, "=="); |
| 6248 | | op_id = .EqualEqual; |
| 6249 | | }, |
| 6250 | | .Slash => { |
| 6251 | | op_id = .Div; |
| 6252 | | op_token = try appendToken(c, .Slash, "/"); |
| 6253 | | }, |
| 6254 | | .Percent => { |
| 6255 | | op_id = .Mod; |
| 6256 | | op_token = try appendToken(c, .Percent, "%"); |
| 6257 | | }, |
| 6258 | | .StringLiteral => { |
| 6259 | | op_id = .ArrayCat; |
| 6260 | | op_token = try appendToken(c, .PlusPlus, "++"); |
| 6261 | | |
| 6262 | | m.i -= 1; |
| 6263 | | }, |
| 6264 | | .Identifier => { |
| 6265 | | op_id = .ArrayCat; |
| 6266 | | op_token = try appendToken(c, .PlusPlus, "++"); |
| 6267 | | |
| 6268 | | m.i -= 1; |
| 6484 | .PlusPlus, .MinusMinus => { |
| 6485 | try m.fail(c, "TODO postfix inc/dec expr", .{}); |
| 6486 | return error.ParseError; |
| 6269 | 6487 | }, |
| 6270 | 6488 | else => { |
| 6271 | 6489 | m.i -= 1; |
| 6272 | 6490 | return node; |
| 6273 | 6491 | }, |
| 6274 | 6492 | } |
| 6275 | | const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt; |
| 6276 | | const lhs_node = try cast_fn(c, node); |
| 6277 | | const rhs_node = try parseCPrefixOpExpr(c, m, scope); |
| 6278 | | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6279 | | op_node.* = .{ |
| 6280 | | .base = .{ .tag = op_id }, |
| 6281 | | .op_token = op_token, |
| 6282 | | .lhs = lhs_node, |
| 6283 | | .rhs = try cast_fn(c, rhs_node), |
| 6284 | | }; |
| 6285 | | node = &op_node.base; |
| 6286 | 6493 | } |
| 6287 | 6494 | } |
| 6288 | 6495 | |
| 6289 | | fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6496 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6290 | 6497 | switch (m.next().?) { |
| 6291 | 6498 | .Bang => { |
| 6292 | 6499 | const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!"); |
| 6293 | | node.rhs = try parseCPrefixOpExpr(c, m, scope); |
| 6500 | node.rhs = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope)); |
| 6294 | 6501 | return &node.base; |
| 6295 | 6502 | }, |
| 6296 | 6503 | .Minus => { |
| 6297 | 6504 | const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-"); |
| 6298 | | node.rhs = try parseCPrefixOpExpr(c, m, scope); |
| 6505 | node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope)); |
| 6299 | 6506 | return &node.base; |
| 6300 | 6507 | }, |
| 6301 | | .Plus => return try parseCPrefixOpExpr(c, m, scope), |
| 6508 | .Plus => return try parseCUnaryExpr(c, m, scope), |
| 6302 | 6509 | .Tilde => { |
| 6303 | 6510 | const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~"); |
| 6304 | | node.rhs = try parseCPrefixOpExpr(c, m, scope); |
| 6511 | node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope)); |
| 6305 | 6512 | return &node.base; |
| 6306 | 6513 | }, |
| 6307 | 6514 | .Asterisk => { |
| 6308 | | const node = try parseCPrefixOpExpr(c, m, scope); |
| 6515 | const node = try macroGroup(c, try parseCUnaryExpr(c, m, scope)); |
| 6309 | 6516 | return try transCreateNodePtrDeref(c, node); |
| 6310 | 6517 | }, |
| 6311 | 6518 | .Ampersand => { |
| 6312 | 6519 | const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&"); |
| 6313 | | node.rhs = try parseCPrefixOpExpr(c, m, scope); |
| 6520 | node.rhs = try macroGroup(c, try parseCUnaryExpr(c, m, scope)); |
| 6314 | 6521 | return &node.base; |
| 6315 | 6522 | }, |
| 6316 | 6523 | .Keyword_sizeof => { |
| 6317 | 6524 | const inner = if (m.peek().? == .LParen) blk: { |
| 6318 | 6525 | _ = m.next(); |
| 6319 | | const inner = try parseCExpr(c, m, scope); |
| 6526 | // C grammar says this should be 'type-name' but we have to |
| 6527 | // use parseCMulExpr to correctly handle pointer types. |
| 6528 | const inner = try parseCMulExpr(c, m, scope); |
| 6320 | 6529 | if (m.next().? != .RParen) { |
| 6321 | 6530 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 6322 | 6531 | return error.ParseError; |
| 6323 | 6532 | } |
| 6324 | 6533 | break :blk inner; |
| 6325 | | } else try parseCPrefixOpExpr(c, m, scope); |
| 6534 | } else try parseCUnaryExpr(c, m, scope); |
| 6326 | 6535 | |
| 6327 | 6536 | //(@import("std").meta.sizeof(dest, x)) |
| 6328 | 6537 | const import_fn_call = try c.createBuiltinCall("@import", 1); |
| ... | ... | @@ -6344,7 +6553,9 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6344 | 6553 | try m.fail(c, "unable to translate C expr: expected '('", .{}); |
| 6345 | 6554 | return error.ParseError; |
| 6346 | 6555 | } |
| 6347 | | const inner = try parseCExpr(c, m, scope); |
| 6556 | // C grammar says this should be 'type-name' but we have to |
| 6557 | // use parseCMulExpr to correctly handle pointer types. |
| 6558 | const inner = try parseCMulExpr(c, m, scope); |
| 6348 | 6559 | if (m.next().? != .RParen) { |
| 6349 | 6560 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 6350 | 6561 | return error.ParseError; |
| ... | ... | @@ -6355,9 +6566,13 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6355 | 6566 | builtin_call.rparen_token = try appendToken(c, .RParen, ")"); |
| 6356 | 6567 | return &builtin_call.base; |
| 6357 | 6568 | }, |
| 6569 | .PlusPlus, .MinusMinus => { |
| 6570 | try m.fail(c, "TODO unary inc/dec expr", .{}); |
| 6571 | return error.ParseError; |
| 6572 | }, |
| 6358 | 6573 | else => { |
| 6359 | 6574 | m.i -= 1; |
| 6360 | | return try parseCSuffixOpExpr(c, m, scope); |
| 6575 | return try parseCPostfixExpr(c, m, scope); |
| 6361 | 6576 | }, |
| 6362 | 6577 | } |
| 6363 | 6578 | } |