| ... | @@ -5527,58 +5527,41 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5527,58 +5527,41 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5527 | const ParseError = Error || error{ParseError}; | 5527 | const ParseError = Error || error{ParseError}; |
| 5528 | | 5528 | |
| 5529 | fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { | 5529 | fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5530 | const node = try parseCPrefixOpExpr(c, m, scope); | 5530 | // TODO parseCAssignExpr here |
| 5531 | switch (m.next().?) { | 5531 | const node = try parseCCondExpr(c, m, scope); |
| 5532 | .QuestionMark => { | 5532 | if (m.next().? != .Comma) { |
| 5533 | // must come immediately after expr | 5533 | m.i -= 1; |
| 5534 | _ = try appendToken(c, .RParen, ")"); | 5534 | return node; |
| 5535 | const if_node = try transCreateNodeIf(c); | 5535 | } |
| 5536 | if_node.condition = node; | 5536 | _ = try appendToken(c, .Semicolon, ";"); |
| 5537 | if_node.body = try parseCPrimaryExpr(c, m, scope); | 5537 | var block_scope = try Scope.Block.init(c, scope, true); |
| 5538 | if (m.next().? != .Colon) { | 5538 | defer block_scope.deinit(); |
| 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); | | |
| 5564 | | 5539 | |
| 5565 | last = try parseCPrefixOpExpr(c, m, scope); | 5540 | var last = node; |
| 5566 | _ = try appendToken(c, .Semicolon, ";"); | 5541 | while (true) { |
| 5567 | if (m.next().? != .Comma) { | 5542 | // suppress result |
| 5568 | m.i -= 1; | 5543 | const lhs = try transCreateNodeIdentifier(c, "_"); |
| 5569 | break; | 5544 | const op_token = try appendToken(c, .Equal, "="); |
| 5570 | } | 5545 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 5571 | } | 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); | 5554 | last = try parseCCondExpr(c, m, scope); |
| 5574 | try block_scope.statements.append(&break_node.base); | 5555 | _ = try appendToken(c, .Semicolon, ";"); |
| 5575 | return try block_scope.complete(c); | 5556 | if (m.next().? != .Comma) { |
| 5576 | }, | | |
| 5577 | else => { | | |
| 5578 | m.i -= 1; | 5557 | m.i -= 1; |
| 5579 | return node; | 5558 | break; |
| 5580 | }, | 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 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { | 5567 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { |
| ... | @@ -5805,7 +5788,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5805,7 +5788,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5805 | return bytes[0..i]; | 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 | const tok = m.next().?; | 5792 | const tok = m.next().?; |
| 5810 | const slice = m.slice(); | 5793 | const slice = m.slice(); |
| 5811 | switch (tok) { | 5794 | switch (tok) { |
| ... | @@ -5952,6 +5935,30 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N | ... | @@ -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 | fn nodeIsInfixOp(tag: ast.Node.Tag) bool { | 5962 | fn nodeIsInfixOp(tag: ast.Node.Tag) bool { |
| 5956 | return switch (tag) { | 5963 | return switch (tag) { |
| 5957 | .Add, | 5964 | .Add, |
| ... | @@ -6053,31 +6060,268 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { | ... | @@ -6053,31 +6060,268 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { |
| 6053 | return &group_node.base; | 6060 | return &group_node.base; |
| 6054 | } | 6061 | } |
| 6055 | | 6062 | |
| 6056 | fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { | 6063 | fn macroGroup(c: *Context, node: *ast.Node) !*ast.Node { |
| 6057 | var node = try parseCPrimaryExpr(c, m, scope); | 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 | while (true) { | 6193 | while (true) { |
| 6059 | var op_token: ast.TokenIndex = undefined; | 6194 | var op_token: ast.TokenIndex = undefined; |
| 6060 | var op_id: ast.Node.Tag = undefined; | 6195 | var op_id: ast.Node.Tag = undefined; |
| 6061 | var bool_op = false; | 6196 | switch (m.peek().?) { |
| 6062 | switch (m.next().?) { | 6197 | .BangEqual => { |
| 6063 | .Period => { | 6198 | op_token = try appendToken(c, .BangEqual, "!="); |
| 6064 | if (m.next().? != .Identifier) { | 6199 | op_id = .BangEqual; |
| 6065 | try m.fail(c, "unable to translate C expr: expected identifier", .{}); | 6200 | }, |
| 6066 | return error.ParseError; | 6201 | .EqualEqual => { |
| 6067 | } | 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()); | 6221 | fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 6070 | continue; | 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 => { | 6231 | .AngleBracketRightEqual => { |
| 6073 | if (m.next().? != .Identifier) { | 6232 | op_token = try appendToken(c, .AngleBracketRightEqual, ">="); |
| 6074 | try m.fail(c, "unable to translate C expr: expected identifier", .{}); | 6233 | op_id = .GreaterOrEqual; |
| 6075 | return error.ParseError; | 6234 | }, |
| 6076 | } | 6235 | .AngleBracketLeft => { |
| 6077 | const deref = try transCreateNodePtrDeref(c, node); | 6236 | op_token = try appendToken(c, .AngleBracketLeft, "<"); |
| 6078 | node = try transCreateNodeFieldAccess(c, deref, m.slice()); | 6237 | op_id = .LessThan; |
| 6079 | continue; | | |
| 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 | .Asterisk => { | 6325 | .Asterisk => { |
| 6082 | if (m.peek().? == .RParen) { | 6326 | if (m.peek().? == .RParen) { |
| 6083 | // type *) | 6327 | // type *) |
| ... | @@ -6105,59 +6349,57 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. | ... | @@ -6105,59 +6349,57 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6105 | op_id = .BitShiftLeft; | 6349 | op_id = .BitShiftLeft; |
| 6106 | } | 6350 | } |
| 6107 | }, | 6351 | }, |
| 6108 | .AngleBracketAngleBracketLeft => { | 6352 | .Slash => { |
| 6109 | op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<"); | 6353 | op_id = .Div; |
| 6110 | op_id = .BitShiftLeft; | 6354 | op_token = try appendToken(c, .Slash, "/"); |
| 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; | | |
| 6141 | }, | 6355 | }, |
| 6142 | .AngleBracketRight => { | 6356 | .Percent => { |
| 6143 | op_token = try appendToken(c, .AngleBracketRight, ">"); | 6357 | op_id = .Mod; |
| 6144 | op_id = .GreaterThan; | 6358 | op_token = try appendToken(c, .Percent, "%"); |
| 6145 | }, | 6359 | }, |
| 6146 | .AngleBracketRightEqual => { | 6360 | else => { |
| 6147 | op_token = try appendToken(c, .AngleBracketRightEqual, ">="); | 6361 | m.i -= 1; |
| 6148 | op_id = .GreaterOrEqual; | 6362 | return node; |
| 6149 | }, | 6363 | }, |
| 6150 | .AngleBracketLeft => { | 6364 | } |
| 6151 | op_token = try appendToken(c, .AngleBracketLeft, "<"); | 6365 | const lhs_node = try macroBoolToInt(c, node); |
| 6152 | op_id = .LessThan; | 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 => { | 6391 | .Arrow => { |
| 6155 | op_token = try appendToken(c, .AngleBracketLeftEqual, "<="); | 6392 | if (m.next().? != .Identifier) { |
| 6156 | op_id = .LessOrEqual; | 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 | .LBracket => { | 6400 | .LBracket => { |
| 6159 | const arr_node = try transCreateNodeArrayAccess(c, node); | 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 | arr_node.rtoken = try appendToken(c, .RBracket, "]"); | 6403 | arr_node.rtoken = try appendToken(c, .RBracket, "]"); |
| 6162 | node = &arr_node.base; | 6404 | node = &arr_node.base; |
| 6163 | if (m.next().? != .RBracket) { | 6405 | if (m.next().? != .RBracket) { |
| ... | @@ -6171,7 +6413,7 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. | ... | @@ -6171,7 +6413,7 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6171 | var call_params = std.ArrayList(*ast.Node).init(c.gpa); | 6413 | var call_params = std.ArrayList(*ast.Node).init(c.gpa); |
| 6172 | defer call_params.deinit(); | 6414 | defer call_params.deinit(); |
| 6173 | while (true) { | 6415 | while (true) { |
| 6174 | const arg = try parseCPrefixOpExpr(c, m, scope); | 6416 | const arg = try parseCCondExpr(c, m, scope); |
| 6175 | try call_params.append(arg); | 6417 | try call_params.append(arg); |
| 6176 | switch (m.next().?) { | 6418 | switch (m.next().?) { |
| 6177 | .Comma => _ = try appendToken(c, .Comma, ","), | 6419 | .Comma => _ = try appendToken(c, .Comma, ","), |
| ... | @@ -6204,7 +6446,7 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. | ... | @@ -6204,7 +6446,7 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6204 | defer init_vals.deinit(); | 6446 | defer init_vals.deinit(); |
| 6205 | | 6447 | |
| 6206 | while (true) { | 6448 | while (true) { |
| 6207 | const val = try parseCPrefixOpExpr(c, m, scope); | 6449 | const val = try parseCCondExpr(c, m, scope); |
| 6208 | try init_vals.append(val); | 6450 | try init_vals.append(val); |
| 6209 | switch (m.next().?) { | 6451 | switch (m.next().?) { |
| 6210 | .Comma => _ = try appendToken(c, .Comma, ","), | 6452 | .Comma => _ = try appendToken(c, .Comma, ","), |
| ... | @@ -6239,90 +6481,57 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. | ... | @@ -6239,90 +6481,57 @@ fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6239 | node = &zero_init_call.base; | 6481 | node = &zero_init_call.base; |
| 6240 | continue; | 6482 | continue; |
| 6241 | }, | 6483 | }, |
| 6242 | .BangEqual => { | 6484 | .PlusPlus, .MinusMinus => { |
| 6243 | op_token = try appendToken(c, .BangEqual, "!="); | 6485 | try m.fail(c, "TODO postfix inc/dec expr", .{}); |
| 6244 | op_id = .BangEqual; | 6486 | return error.ParseError; |
| 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; | | |
| 6269 | }, | 6487 | }, |
| 6270 | else => { | 6488 | else => { |
| 6271 | m.i -= 1; | 6489 | m.i -= 1; |
| 6272 | return node; | 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 | switch (m.next().?) { | 6497 | switch (m.next().?) { |
| 6291 | .Bang => { | 6498 | .Bang => { |
| 6292 | const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!"); | 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 | return &node.base; | 6501 | return &node.base; |
| 6295 | }, | 6502 | }, |
| 6296 | .Minus => { | 6503 | .Minus => { |
| 6297 | const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-"); | 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 | return &node.base; | 6506 | return &node.base; |
| 6300 | }, | 6507 | }, |
| 6301 | .Plus => return try parseCPrefixOpExpr(c, m, scope), | 6508 | .Plus => return try parseCUnaryExpr(c, m, scope), |
| 6302 | .Tilde => { | 6509 | .Tilde => { |
| 6303 | const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~"); | 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 | return &node.base; | 6512 | return &node.base; |
| 6306 | }, | 6513 | }, |
| 6307 | .Asterisk => { | 6514 | .Asterisk => { |
| 6308 | const node = try parseCPrefixOpExpr(c, m, scope); | 6515 | const node = try macroGroup(c, try parseCUnaryExpr(c, m, scope)); |
| 6309 | return try transCreateNodePtrDeref(c, node); | 6516 | return try transCreateNodePtrDeref(c, node); |
| 6310 | }, | 6517 | }, |
| 6311 | .Ampersand => { | 6518 | .Ampersand => { |
| 6312 | const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&"); | 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 | return &node.base; | 6521 | return &node.base; |
| 6315 | }, | 6522 | }, |
| 6316 | .Keyword_sizeof => { | 6523 | .Keyword_sizeof => { |
| 6317 | const inner = if (m.peek().? == .LParen) blk: { | 6524 | const inner = if (m.peek().? == .LParen) blk: { |
| 6318 | _ = m.next(); | 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 | if (m.next().? != .RParen) { | 6529 | if (m.next().? != .RParen) { |
| 6321 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); | 6530 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 6322 | return error.ParseError; | 6531 | return error.ParseError; |
| 6323 | } | 6532 | } |
| 6324 | break :blk inner; | 6533 | break :blk inner; |
| 6325 | } else try parseCPrefixOpExpr(c, m, scope); | 6534 | } else try parseCUnaryExpr(c, m, scope); |
| 6326 | | 6535 | |
| 6327 | //(@import("std").meta.sizeof(dest, x)) | 6536 | //(@import("std").meta.sizeof(dest, x)) |
| 6328 | const import_fn_call = try c.createBuiltinCall("@import", 1); | 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,7 +6553,9 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6344 | try m.fail(c, "unable to translate C expr: expected '('", .{}); | 6553 | try m.fail(c, "unable to translate C expr: expected '('", .{}); |
| 6345 | return error.ParseError; | 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 | if (m.next().? != .RParen) { | 6559 | if (m.next().? != .RParen) { |
| 6349 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); | 6560 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 6350 | return error.ParseError; | 6561 | return error.ParseError; |
| ... | @@ -6355,9 +6566,13 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. | ... | @@ -6355,9 +6566,13 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6355 | builtin_call.rparen_token = try appendToken(c, .RParen, ")"); | 6566 | builtin_call.rparen_token = try appendToken(c, .RParen, ")"); |
| 6356 | return &builtin_call.base; | 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 | else => { | 6573 | else => { |
| 6359 | m.i -= 1; | 6574 | m.i -= 1; |
| 6360 | return try parseCSuffixOpExpr(c, m, scope); | 6575 | return try parseCPostfixExpr(c, m, scope); |
| 6361 | }, | 6576 | }, |
| 6362 | } | 6577 | } |
| 6363 | } | 6578 | } |