| ... | ... | @@ -6,8 +6,9 @@ const assert = std.debug.assert; |
| 6 | 6 | const ast = std.zig.ast; |
| 7 | 7 | const Token = std.zig.Token; |
| 8 | 8 | usingnamespace @import("clang.zig"); |
| 9 | | const ctok = @import("c_tokenizer.zig"); |
| 10 | | const CToken = ctok.CToken; |
| 9 | const ctok = std.c.tokenizer; |
| 10 | const CToken = std.c.Token; |
| 11 | const CTokenList = std.c.tokenizer.Source.TokenList; |
| 11 | 12 | const mem = std.mem; |
| 12 | 13 | const math = std.math; |
| 13 | 14 | |
| ... | ... | @@ -4818,7 +4819,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4818 | 4819 | // TODO if we see #undef, delete it from the table |
| 4819 | 4820 | var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(unit); |
| 4820 | 4821 | const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(unit); |
| 4821 | | var tok_list = ctok.TokenList.init(c.a()); |
| 4822 | var tok_list = CTokenList.init(c.a()); |
| 4822 | 4823 | const scope = c.global_scope; |
| 4823 | 4824 | |
| 4824 | 4825 | while (it.I != it_end.I) : (it.I += 1) { |
| ... | ... | @@ -4829,6 +4830,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4829 | 4830 | const macro = @ptrCast(*ZigClangMacroDefinitionRecord, entity); |
| 4830 | 4831 | const raw_name = ZigClangMacroDefinitionRecord_getName_getNameStart(macro); |
| 4831 | 4832 | const begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro); |
| 4833 | // const end_loc = ZigClangMacroDefinitionRecord_getSourceRange_getEnd(macro); |
| 4832 | 4834 | |
| 4833 | 4835 | const name = try c.str(raw_name); |
| 4834 | 4836 | // TODO https://github.com/ziglang/zig/issues/3756 |
| ... | ... | @@ -4839,42 +4841,61 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4839 | 4841 | } |
| 4840 | 4842 | |
| 4841 | 4843 | const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); |
| 4842 | | ctok.tokenizeCMacro(c, begin_loc, mangled_name, &tok_list, begin_c) catch |err| switch (err) { |
| 4843 | | error.OutOfMemory => |e| return e, |
| 4844 | | else => { |
| 4845 | | continue; |
| 4844 | // const end_c = ZigClangSourceManager_getCharacterData(c.source_manager, end_loc); |
| 4845 | // const slice = begin_c[0 .. @ptrToInt(end_c) - @ptrToInt(begin_c)]; |
| 4846 | const slice = begin_c[0..mem.len(u8, begin_c)]; |
| 4847 | |
| 4848 | tok_list.shrink(0); |
| 4849 | var tokenizer = std.c.Tokenizer{ |
| 4850 | .source = &std.c.tokenizer.Source{ |
| 4851 | .buffer = slice, |
| 4852 | .file_name = undefined, |
| 4853 | .tokens = undefined, |
| 4846 | 4854 | }, |
| 4847 | 4855 | }; |
| 4856 | while (true) { |
| 4857 | const tok = tokenizer.next(); |
| 4858 | switch (tok.id) { |
| 4859 | .Nl, .Eof => { |
| 4860 | try tok_list.push(tok); |
| 4861 | break; |
| 4862 | }, |
| 4863 | .LineComment, .MultiLineComment => continue, |
| 4864 | else => {}, |
| 4865 | } |
| 4866 | try tok_list.push(tok); |
| 4867 | } |
| 4848 | 4868 | |
| 4849 | 4869 | var tok_it = tok_list.iterator(0); |
| 4850 | 4870 | const first_tok = tok_it.next().?; |
| 4851 | | assert(first_tok.id == .Identifier and mem.eql(u8, first_tok.bytes, name)); |
| 4871 | assert(first_tok.id == .Identifier and mem.eql(u8, slice[first_tok.start..first_tok.end], name)); |
| 4872 | |
| 4873 | var macro_fn = false; |
| 4852 | 4874 | const next = tok_it.peek().?; |
| 4853 | 4875 | switch (next.id) { |
| 4854 | 4876 | .Identifier => { |
| 4855 | 4877 | // if it equals itself, ignore. for example, from stdio.h: |
| 4856 | 4878 | // #define stdin stdin |
| 4857 | | if (mem.eql(u8, name, next.bytes)) { |
| 4879 | if (mem.eql(u8, name, slice[next.start..next.end])) { |
| 4858 | 4880 | continue; |
| 4859 | 4881 | } |
| 4860 | 4882 | }, |
| 4861 | | .Eof => { |
| 4883 | .Nl, .Eof => { |
| 4862 | 4884 | // this means it is a macro without a value |
| 4863 | 4885 | // we don't care about such things |
| 4864 | 4886 | continue; |
| 4865 | 4887 | }, |
| 4888 | .LParen => { |
| 4889 | // if the name is immediately followed by a '(' then it is a function |
| 4890 | macro_fn = first_tok.end == next.start; |
| 4891 | }, |
| 4866 | 4892 | else => {}, |
| 4867 | 4893 | } |
| 4868 | 4894 | |
| 4869 | | const macro_fn = if (tok_it.peek().?.id == .Fn) blk: { |
| 4870 | | _ = tok_it.next(); |
| 4871 | | break :blk true; |
| 4872 | | } else false; |
| 4873 | | |
| 4874 | 4895 | (if (macro_fn) |
| 4875 | | transMacroFnDefine(c, &tok_it, mangled_name, begin_loc) |
| 4896 | transMacroFnDefine(c, &tok_it, slice, mangled_name, begin_loc) |
| 4876 | 4897 | else |
| 4877 | | transMacroDefine(c, &tok_it, mangled_name, begin_loc)) catch |err| switch (err) { |
| 4898 | transMacroDefine(c, &tok_it, slice, mangled_name, begin_loc)) catch |err| switch (err) { |
| 4878 | 4899 | error.ParseError => continue, |
| 4879 | 4900 | error.OutOfMemory => |e| return e, |
| 4880 | 4901 | }; |
| ... | ... | @@ -4884,15 +4905,15 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4884 | 4905 | } |
| 4885 | 4906 | } |
| 4886 | 4907 | |
| 4887 | | fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 4908 | fn transMacroDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 4888 | 4909 | const scope = &c.global_scope.base; |
| 4889 | 4910 | |
| 4890 | 4911 | const node = try transCreateNodeVarDecl(c, true, true, name); |
| 4891 | 4912 | node.eq_token = try appendToken(c, .Equal, "="); |
| 4892 | 4913 | |
| 4893 | | node.init_node = try parseCExpr(c, it, source_loc, scope); |
| 4914 | node.init_node = try parseCExpr(c, it, source, source_loc, scope); |
| 4894 | 4915 | const last = it.next().?; |
| 4895 | | if (last.id != .Eof) |
| 4916 | if (last.id != .Eof and last.id != .Nl) |
| 4896 | 4917 | return failDecl( |
| 4897 | 4918 | c, |
| 4898 | 4919 | source_loc, |
| ... | ... | @@ -4905,7 +4926,7 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, |
| 4905 | 4926 | _ = try c.global_scope.macro_table.put(name, &node.base); |
| 4906 | 4927 | } |
| 4907 | 4928 | |
| 4908 | | fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 4929 | fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 4909 | 4930 | const block_scope = try Scope.Block.init(c, &c.global_scope.base, null); |
| 4910 | 4931 | const scope = &block_scope.base; |
| 4911 | 4932 | |
| ... | ... | @@ -4937,7 +4958,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 4937 | 4958 | ); |
| 4938 | 4959 | } |
| 4939 | 4960 | |
| 4940 | | const mangled_name = try block_scope.makeMangledName(c, param_tok.bytes); |
| 4961 | const mangled_name = try block_scope.makeMangledName(c, source[param_tok.start..param_tok.end]); |
| 4941 | 4962 | const param_name_tok = try appendIdentifier(c, mangled_name); |
| 4942 | 4963 | _ = try appendToken(c, .Colon, ":"); |
| 4943 | 4964 | |
| ... | ... | @@ -5000,7 +5021,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 5000 | 5021 | const block = try transCreateNodeBlock(c, null); |
| 5001 | 5022 | |
| 5002 | 5023 | const return_expr = try transCreateNodeReturnExpr(c); |
| 5003 | | const expr = try parseCExpr(c, it, source_loc, scope); |
| 5024 | const expr = try parseCExpr(c, it, source, source_loc, scope); |
| 5004 | 5025 | const last = it.next().?; |
| 5005 | 5026 | if (last.id != .Eof) |
| 5006 | 5027 | return failDecl( |
| ... | ... | @@ -5022,27 +5043,28 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 5022 | 5043 | |
| 5023 | 5044 | const ParseError = Error || error{ParseError}; |
| 5024 | 5045 | |
| 5025 | | fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5026 | | const node = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5046 | fn parseCExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5047 | const node = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5027 | 5048 | switch (it.next().?.id) { |
| 5028 | 5049 | .QuestionMark => { |
| 5029 | 5050 | // must come immediately after expr |
| 5030 | 5051 | _ = try appendToken(c, .RParen, ")"); |
| 5031 | 5052 | const if_node = try transCreateNodeIf(c); |
| 5032 | 5053 | if_node.condition = node; |
| 5033 | | if_node.body = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 5054 | if_node.body = try parseCPrimaryExpr(c, it, source, source_loc, scope); |
| 5034 | 5055 | if (it.next().?.id != .Colon) { |
| 5056 | const first_tok = it.list.at(0); |
| 5035 | 5057 | try failDecl( |
| 5036 | 5058 | c, |
| 5037 | 5059 | source_loc, |
| 5038 | | it.list.at(0).*.bytes, |
| 5060 | source[first_tok.start..first_tok.end], |
| 5039 | 5061 | "unable to translate C expr: expected ':'", |
| 5040 | 5062 | .{}, |
| 5041 | 5063 | ); |
| 5042 | 5064 | return error.ParseError; |
| 5043 | 5065 | } |
| 5044 | 5066 | if_node.@"else" = try transCreateNodeElse(c); |
| 5045 | | if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 5067 | if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source, source_loc, scope); |
| 5046 | 5068 | return &if_node.base; |
| 5047 | 5069 | }, |
| 5048 | 5070 | else => { |
| ... | ... | @@ -5052,30 +5074,30 @@ fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSou |
| 5052 | 5074 | } |
| 5053 | 5075 | } |
| 5054 | 5076 | |
| 5055 | | fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node { |
| 5056 | | if (tok.id == .NumLitInt) { |
| 5057 | | var lit_bytes = tok.bytes; |
| 5077 | fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigClangSourceLocation) ParseError!*ast.Node { |
| 5078 | var lit_bytes = source[tok.start..tok.end]; |
| 5058 | 5079 | |
| 5059 | | if (tok.bytes.len > 2 and tok.bytes[0] == '0') { |
| 5060 | | switch (tok.bytes[1]) { |
| 5080 | if (tok.id == .IntegerLiteral) { |
| 5081 | if (lit_bytes.len > 2 and lit_bytes[0] == '0') { |
| 5082 | switch (lit_bytes[1]) { |
| 5061 | 5083 | '0'...'7' => { |
| 5062 | 5084 | // Octal |
| 5063 | | lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{tok.bytes}); |
| 5085 | lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{lit_bytes}); |
| 5064 | 5086 | }, |
| 5065 | 5087 | 'X' => { |
| 5066 | 5088 | // Hexadecimal with capital X, valid in C but not in Zig |
| 5067 | | lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{tok.bytes[2..]}); |
| 5089 | lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]}); |
| 5068 | 5090 | }, |
| 5069 | 5091 | else => {}, |
| 5070 | 5092 | } |
| 5071 | 5093 | } |
| 5072 | 5094 | |
| 5073 | | if (tok.num_lit_suffix == .None) { |
| 5095 | if (tok.id.IntegerLiteral == .None) { |
| 5074 | 5096 | return transCreateNodeInt(c, lit_bytes); |
| 5075 | 5097 | } |
| 5076 | 5098 | |
| 5077 | 5099 | const cast_node = try transCreateNodeBuiltinFnCall(c, "@as"); |
| 5078 | | try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) { |
| 5100 | try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.id.IntegerLiteral) { |
| 5079 | 5101 | .U => "c_uint", |
| 5080 | 5102 | .L => "c_long", |
| 5081 | 5103 | .LU => "c_ulong", |
| ... | ... | @@ -5083,55 +5105,216 @@ fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) P |
| 5083 | 5105 | .LLU => "c_ulonglong", |
| 5084 | 5106 | else => unreachable, |
| 5085 | 5107 | })); |
| 5108 | lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (tok.id.IntegerLiteral) { |
| 5109 | .U, .L => @as(u8, 1), |
| 5110 | .LU, .LL => 2, |
| 5111 | .LLU => 3, |
| 5112 | else => unreachable, |
| 5113 | }]; |
| 5086 | 5114 | _ = try appendToken(c, .Comma, ","); |
| 5087 | 5115 | try cast_node.params.push(try transCreateNodeInt(c, lit_bytes)); |
| 5088 | 5116 | cast_node.rparen_token = try appendToken(c, .RParen, ")"); |
| 5089 | 5117 | return &cast_node.base; |
| 5090 | | } else if (tok.id == .NumLitFloat) { |
| 5091 | | if (tok.num_lit_suffix == .None) { |
| 5092 | | return transCreateNodeFloat(c, tok.bytes); |
| 5118 | } else if (tok.id == .FloatLiteral) { |
| 5119 | if (tok.id.FloatLiteral == .None) { |
| 5120 | return transCreateNodeFloat(c, lit_bytes); |
| 5093 | 5121 | } |
| 5094 | 5122 | const cast_node = try transCreateNodeBuiltinFnCall(c, "@as"); |
| 5095 | | try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) { |
| 5123 | try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.id.FloatLiteral) { |
| 5096 | 5124 | .F => "f32", |
| 5097 | 5125 | .L => "f64", |
| 5098 | 5126 | else => unreachable, |
| 5099 | 5127 | })); |
| 5100 | 5128 | _ = try appendToken(c, .Comma, ","); |
| 5101 | | try cast_node.params.push(try transCreateNodeFloat(c, tok.bytes)); |
| 5129 | try cast_node.params.push(try transCreateNodeFloat(c, lit_bytes[0 .. lit_bytes.len - 1])); |
| 5102 | 5130 | cast_node.rparen_token = try appendToken(c, .RParen, ")"); |
| 5103 | 5131 | return &cast_node.base; |
| 5104 | 5132 | } else unreachable; |
| 5105 | 5133 | } |
| 5106 | 5134 | |
| 5107 | | fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5135 | fn zigifyEscapeSequences(ctx: *Context, source: []const u8, name: []const u8, source_loc: ZigClangSourceLocation) ![]const u8 { |
| 5136 | for (source) |c| { |
| 5137 | if (c == '\\') { |
| 5138 | break; |
| 5139 | } |
| 5140 | } else return source; |
| 5141 | var bytes = try ctx.a().alloc(u8, source.len * 2); |
| 5142 | var state: enum { |
| 5143 | Start, |
| 5144 | Escape, |
| 5145 | Hex, |
| 5146 | Octal, |
| 5147 | } = .Start; |
| 5148 | var i: usize = 0; |
| 5149 | var count: u8 = 0; |
| 5150 | var num: u8 = 0; |
| 5151 | for (source) |c| { |
| 5152 | switch (state) { |
| 5153 | .Escape => { |
| 5154 | switch (c) { |
| 5155 | 'n', 'r', 't', '\\', '\'', '\"' => { |
| 5156 | bytes[i] = c; |
| 5157 | }, |
| 5158 | '0'...'7' => { |
| 5159 | count += 1; |
| 5160 | num += c - '0'; |
| 5161 | state = .Octal; |
| 5162 | bytes[i] = 'x'; |
| 5163 | }, |
| 5164 | 'x' => { |
| 5165 | state = .Hex; |
| 5166 | bytes[i] = 'x'; |
| 5167 | }, |
| 5168 | 'a' => { |
| 5169 | bytes[i] = 'x'; |
| 5170 | i += 1; |
| 5171 | bytes[i] = '0'; |
| 5172 | i += 1; |
| 5173 | bytes[i] = '7'; |
| 5174 | }, |
| 5175 | 'b' => { |
| 5176 | bytes[i] = 'x'; |
| 5177 | i += 1; |
| 5178 | bytes[i] = '0'; |
| 5179 | i += 1; |
| 5180 | bytes[i] = '8'; |
| 5181 | }, |
| 5182 | 'f' => { |
| 5183 | bytes[i] = 'x'; |
| 5184 | i += 1; |
| 5185 | bytes[i] = '0'; |
| 5186 | i += 1; |
| 5187 | bytes[i] = 'C'; |
| 5188 | }, |
| 5189 | 'v' => { |
| 5190 | bytes[i] = 'x'; |
| 5191 | i += 1; |
| 5192 | bytes[i] = '0'; |
| 5193 | i += 1; |
| 5194 | bytes[i] = 'B'; |
| 5195 | }, |
| 5196 | '?' => { |
| 5197 | i -= 1; |
| 5198 | bytes[i] = '?'; |
| 5199 | }, |
| 5200 | 'u', 'U' => { |
| 5201 | try failDecl(ctx, source_loc, name, "macro tokenizing failed: TODO unicode escape sequences", .{}); |
| 5202 | return error.ParseError; |
| 5203 | }, |
| 5204 | else => { |
| 5205 | try failDecl(ctx, source_loc, name, "macro tokenizing failed: unknown escape sequence", .{}); |
| 5206 | return error.ParseError; |
| 5207 | }, |
| 5208 | } |
| 5209 | i += 1; |
| 5210 | if (state == .Escape) |
| 5211 | state = .Start; |
| 5212 | }, |
| 5213 | .Start => { |
| 5214 | if (c == '\\') { |
| 5215 | state = .Escape; |
| 5216 | } |
| 5217 | bytes[i] = c; |
| 5218 | i += 1; |
| 5219 | }, |
| 5220 | .Hex => { |
| 5221 | switch (c) { |
| 5222 | '0'...'9' => { |
| 5223 | num = std.math.mul(u8, num, 16) catch { |
| 5224 | try failDecl(ctx, source_loc, name, "macro tokenizing failed: hex literal overflowed", .{}); |
| 5225 | return error.ParseError; |
| 5226 | }; |
| 5227 | num += c - '0'; |
| 5228 | }, |
| 5229 | 'a'...'f' => { |
| 5230 | num = std.math.mul(u8, num, 16) catch { |
| 5231 | try failDecl(ctx, source_loc, name, "macro tokenizing failed: hex literal overflowed", .{}); |
| 5232 | return error.ParseError; |
| 5233 | }; |
| 5234 | num += c - 'a' + 10; |
| 5235 | }, |
| 5236 | 'A'...'F' => { |
| 5237 | num = std.math.mul(u8, num, 16) catch { |
| 5238 | try failDecl(ctx, source_loc, name, "macro tokenizing failed: hex literal overflowed", .{}); |
| 5239 | return error.ParseError; |
| 5240 | }; |
| 5241 | num += c - 'A' + 10; |
| 5242 | }, |
| 5243 | else => { |
| 5244 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5245 | num = 0; |
| 5246 | if (c == '\\') |
| 5247 | state = .Escape |
| 5248 | else |
| 5249 | state = .Start; |
| 5250 | bytes[i] = c; |
| 5251 | i += 1; |
| 5252 | }, |
| 5253 | } |
| 5254 | }, |
| 5255 | .Octal => { |
| 5256 | const accept_digit = switch (c) { |
| 5257 | // The maximum length of a octal literal is 3 digits |
| 5258 | '0'...'7' => count < 3, |
| 5259 | else => false, |
| 5260 | }; |
| 5261 | |
| 5262 | if (accept_digit) { |
| 5263 | count += 1; |
| 5264 | num = std.math.mul(u8, num, 8) catch { |
| 5265 | try failDecl(ctx, source_loc, name, "macro tokenizing failed: octal literal overflowed", .{}); |
| 5266 | return error.ParseError; |
| 5267 | }; |
| 5268 | num += c - '0'; |
| 5269 | } else { |
| 5270 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5271 | num = 0; |
| 5272 | count = 0; |
| 5273 | if (c == '\\') |
| 5274 | state = .Escape |
| 5275 | else |
| 5276 | state = .Start; |
| 5277 | bytes[i] = c; |
| 5278 | i += 1; |
| 5279 | } |
| 5280 | }, |
| 5281 | } |
| 5282 | } |
| 5283 | if (state == .Hex or state == .Octal) |
| 5284 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5285 | return bytes[0..i]; |
| 5286 | } |
| 5287 | |
| 5288 | fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5108 | 5289 | const tok = it.next().?; |
| 5109 | 5290 | switch (tok.id) { |
| 5110 | | .CharLit => { |
| 5111 | | const token = try appendToken(c, .CharLiteral, tok.bytes); |
| 5291 | .CharLiteral => { |
| 5292 | const first_tok = it.list.at(0); |
| 5293 | const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc)); |
| 5112 | 5294 | const node = try c.a().create(ast.Node.CharLiteral); |
| 5113 | 5295 | node.* = ast.Node.CharLiteral{ |
| 5114 | 5296 | .token = token, |
| 5115 | 5297 | }; |
| 5116 | 5298 | return &node.base; |
| 5117 | 5299 | }, |
| 5118 | | .StrLit => { |
| 5119 | | const token = try appendToken(c, .StringLiteral, tok.bytes); |
| 5300 | .StringLiteral => { |
| 5301 | const first_tok = it.list.at(0); |
| 5302 | const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc)); |
| 5120 | 5303 | const node = try c.a().create(ast.Node.StringLiteral); |
| 5121 | 5304 | node.* = ast.Node.StringLiteral{ |
| 5122 | 5305 | .token = token, |
| 5123 | 5306 | }; |
| 5124 | 5307 | return &node.base; |
| 5125 | 5308 | }, |
| 5126 | | .NumLitInt, .NumLitFloat => { |
| 5127 | | return parseCNumLit(c, tok, source_loc); |
| 5309 | .IntegerLiteral, .FloatLiteral => { |
| 5310 | return parseCNumLit(c, tok, source, source_loc); |
| 5128 | 5311 | }, |
| 5129 | 5312 | .Identifier => { |
| 5130 | | const mangled_name = scope.getAlias(tok.bytes); |
| 5313 | const mangled_name = scope.getAlias(source[tok.start..tok.end]); |
| 5131 | 5314 | return transCreateNodeIdentifier(c, mangled_name); |
| 5132 | 5315 | }, |
| 5133 | 5316 | .LParen => { |
| 5134 | | const inner_node = try parseCExpr(c, it, source_loc, scope); |
| 5317 | const inner_node = try parseCExpr(c, it, source, source_loc, scope); |
| 5135 | 5318 | |
| 5136 | 5319 | if (it.peek().?.id == .RParen) { |
| 5137 | 5320 | _ = it.next(); |
| ... | ... | @@ -5144,13 +5327,14 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC |
| 5144 | 5327 | // hack to get zig fmt to render a comma in builtin calls |
| 5145 | 5328 | _ = try appendToken(c, .Comma, ","); |
| 5146 | 5329 | |
| 5147 | | const node_to_cast = try parseCExpr(c, it, source_loc, scope); |
| 5330 | const node_to_cast = try parseCExpr(c, it, source, source_loc, scope); |
| 5148 | 5331 | |
| 5149 | 5332 | if (it.next().?.id != .RParen) { |
| 5333 | const first_tok = it.list.at(0); |
| 5150 | 5334 | try failDecl( |
| 5151 | 5335 | c, |
| 5152 | 5336 | source_loc, |
| 5153 | | it.list.at(0).*.bytes, |
| 5337 | source[first_tok.start..first_tok.end], |
| 5154 | 5338 | "unable to translate C expr: expected ')''", |
| 5155 | 5339 | .{}, |
| 5156 | 5340 | ); |
| ... | ... | @@ -5228,10 +5412,11 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC |
| 5228 | 5412 | return &if_1.base; |
| 5229 | 5413 | }, |
| 5230 | 5414 | else => { |
| 5415 | const first_tok = it.list.at(0); |
| 5231 | 5416 | try failDecl( |
| 5232 | 5417 | c, |
| 5233 | 5418 | source_loc, |
| 5234 | | it.list.at(0).*.bytes, |
| 5419 | source[first_tok.start..first_tok.end], |
| 5235 | 5420 | "unable to translate C expr: unexpected token {}", |
| 5236 | 5421 | .{tok.id}, |
| 5237 | 5422 | ); |
| ... | ... | @@ -5240,33 +5425,35 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC |
| 5240 | 5425 | } |
| 5241 | 5426 | } |
| 5242 | 5427 | |
| 5243 | | fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5244 | | var node = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 5428 | fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5429 | var node = try parseCPrimaryExpr(c, it, source, source_loc, scope); |
| 5245 | 5430 | while (true) { |
| 5246 | 5431 | const tok = it.next().?; |
| 5247 | 5432 | switch (tok.id) { |
| 5248 | | .Dot => { |
| 5433 | .Period => { |
| 5249 | 5434 | const name_tok = it.next().?; |
| 5250 | 5435 | if (name_tok.id != .Identifier) { |
| 5436 | const first_tok = it.list.at(0); |
| 5251 | 5437 | try failDecl( |
| 5252 | 5438 | c, |
| 5253 | 5439 | source_loc, |
| 5254 | | it.list.at(0).*.bytes, |
| 5440 | source[first_tok.start..first_tok.end], |
| 5255 | 5441 | "unable to translate C expr: expected identifier", |
| 5256 | 5442 | .{}, |
| 5257 | 5443 | ); |
| 5258 | 5444 | return error.ParseError; |
| 5259 | 5445 | } |
| 5260 | 5446 | |
| 5261 | | node = try transCreateNodeFieldAccess(c, node, name_tok.bytes); |
| 5447 | node = try transCreateNodeFieldAccess(c, node, source[name_tok.start..name_tok.end]); |
| 5262 | 5448 | }, |
| 5263 | 5449 | .Arrow => { |
| 5264 | 5450 | const name_tok = it.next().?; |
| 5265 | 5451 | if (name_tok.id != .Identifier) { |
| 5452 | const first_tok = it.list.at(0); |
| 5266 | 5453 | try failDecl( |
| 5267 | 5454 | c, |
| 5268 | 5455 | source_loc, |
| 5269 | | it.list.at(0).*.bytes, |
| 5456 | source[first_tok.start..first_tok.end], |
| 5270 | 5457 | "unable to translate C expr: expected identifier", |
| 5271 | 5458 | .{}, |
| 5272 | 5459 | ); |
| ... | ... | @@ -5274,7 +5461,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5274 | 5461 | } |
| 5275 | 5462 | |
| 5276 | 5463 | const deref = try transCreateNodePtrDeref(c, node); |
| 5277 | | node = try transCreateNodeFieldAccess(c, deref, name_tok.bytes); |
| 5464 | node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]); |
| 5278 | 5465 | }, |
| 5279 | 5466 | .Asterisk => { |
| 5280 | 5467 | if (it.peek().?.id == .RParen) { |
| ... | ... | @@ -5289,7 +5476,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5289 | 5476 | } else { |
| 5290 | 5477 | // expr * expr |
| 5291 | 5478 | const op_token = try appendToken(c, .Asterisk, "*"); |
| 5292 | | const rhs = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 5479 | const rhs = try parseCPrimaryExpr(c, it, source, source_loc, scope); |
| 5293 | 5480 | const mul_node = try c.a().create(ast.Node.InfixOp); |
| 5294 | 5481 | mul_node.* = .{ |
| 5295 | 5482 | .op_token = op_token, |
| ... | ... | @@ -5300,9 +5487,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5300 | 5487 | node = &mul_node.base; |
| 5301 | 5488 | } |
| 5302 | 5489 | }, |
| 5303 | | .Shl => { |
| 5490 | .AngleBracketAngleBracketLeft => { |
| 5304 | 5491 | const op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<"); |
| 5305 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5492 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5306 | 5493 | const bitshift_node = try c.a().create(ast.Node.InfixOp); |
| 5307 | 5494 | bitshift_node.* = .{ |
| 5308 | 5495 | .op_token = op_token, |
| ... | ... | @@ -5312,9 +5499,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5312 | 5499 | }; |
| 5313 | 5500 | node = &bitshift_node.base; |
| 5314 | 5501 | }, |
| 5315 | | .Shr => { |
| 5502 | .AngleBracketAngleBracketRight => { |
| 5316 | 5503 | const op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>"); |
| 5317 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5504 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5318 | 5505 | const bitshift_node = try c.a().create(ast.Node.InfixOp); |
| 5319 | 5506 | bitshift_node.* = .{ |
| 5320 | 5507 | .op_token = op_token, |
| ... | ... | @@ -5326,7 +5513,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5326 | 5513 | }, |
| 5327 | 5514 | .Pipe => { |
| 5328 | 5515 | const op_token = try appendToken(c, .Pipe, "|"); |
| 5329 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5516 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5330 | 5517 | const or_node = try c.a().create(ast.Node.InfixOp); |
| 5331 | 5518 | or_node.* = .{ |
| 5332 | 5519 | .op_token = op_token, |
| ... | ... | @@ -5338,7 +5525,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5338 | 5525 | }, |
| 5339 | 5526 | .Ampersand => { |
| 5340 | 5527 | const op_token = try appendToken(c, .Ampersand, "&"); |
| 5341 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5528 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5342 | 5529 | const bitand_node = try c.a().create(ast.Node.InfixOp); |
| 5343 | 5530 | bitand_node.* = .{ |
| 5344 | 5531 | .op_token = op_token, |
| ... | ... | @@ -5350,7 +5537,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5350 | 5537 | }, |
| 5351 | 5538 | .Plus => { |
| 5352 | 5539 | const op_token = try appendToken(c, .Plus, "+"); |
| 5353 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5540 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5354 | 5541 | const add_node = try c.a().create(ast.Node.InfixOp); |
| 5355 | 5542 | add_node.* = .{ |
| 5356 | 5543 | .op_token = op_token, |
| ... | ... | @@ -5362,7 +5549,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5362 | 5549 | }, |
| 5363 | 5550 | .Minus => { |
| 5364 | 5551 | const op_token = try appendToken(c, .Minus, "-"); |
| 5365 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5552 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5366 | 5553 | const sub_node = try c.a().create(ast.Node.InfixOp); |
| 5367 | 5554 | sub_node.* = .{ |
| 5368 | 5555 | .op_token = op_token, |
| ... | ... | @@ -5372,9 +5559,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5372 | 5559 | }; |
| 5373 | 5560 | node = &sub_node.base; |
| 5374 | 5561 | }, |
| 5375 | | .And => { |
| 5562 | .AmpersandAmpersand => { |
| 5376 | 5563 | const op_token = try appendToken(c, .Keyword_and, "and"); |
| 5377 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5564 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5378 | 5565 | const and_node = try c.a().create(ast.Node.InfixOp); |
| 5379 | 5566 | and_node.* = .{ |
| 5380 | 5567 | .op_token = op_token, |
| ... | ... | @@ -5384,9 +5571,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5384 | 5571 | }; |
| 5385 | 5572 | node = &and_node.base; |
| 5386 | 5573 | }, |
| 5387 | | .Or => { |
| 5574 | .PipePipe => { |
| 5388 | 5575 | const op_token = try appendToken(c, .Keyword_or, "or"); |
| 5389 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5576 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5390 | 5577 | const or_node = try c.a().create(ast.Node.InfixOp); |
| 5391 | 5578 | or_node.* = .{ |
| 5392 | 5579 | .op_token = op_token, |
| ... | ... | @@ -5396,9 +5583,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5396 | 5583 | }; |
| 5397 | 5584 | node = &or_node.base; |
| 5398 | 5585 | }, |
| 5399 | | .Gt => { |
| 5586 | .AngleBracketRight => { |
| 5400 | 5587 | const op_token = try appendToken(c, .AngleBracketRight, ">"); |
| 5401 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5588 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5402 | 5589 | const and_node = try c.a().create(ast.Node.InfixOp); |
| 5403 | 5590 | and_node.* = .{ |
| 5404 | 5591 | .op_token = op_token, |
| ... | ... | @@ -5408,9 +5595,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5408 | 5595 | }; |
| 5409 | 5596 | node = &and_node.base; |
| 5410 | 5597 | }, |
| 5411 | | .Gte => { |
| 5598 | .AngleBracketRightEqual => { |
| 5412 | 5599 | const op_token = try appendToken(c, .AngleBracketRightEqual, ">="); |
| 5413 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5600 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5414 | 5601 | const and_node = try c.a().create(ast.Node.InfixOp); |
| 5415 | 5602 | and_node.* = .{ |
| 5416 | 5603 | .op_token = op_token, |
| ... | ... | @@ -5420,9 +5607,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5420 | 5607 | }; |
| 5421 | 5608 | node = &and_node.base; |
| 5422 | 5609 | }, |
| 5423 | | .Lt => { |
| 5610 | .AngleBracketLeft => { |
| 5424 | 5611 | const op_token = try appendToken(c, .AngleBracketLeft, "<"); |
| 5425 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5612 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5426 | 5613 | const and_node = try c.a().create(ast.Node.InfixOp); |
| 5427 | 5614 | and_node.* = .{ |
| 5428 | 5615 | .op_token = op_token, |
| ... | ... | @@ -5432,9 +5619,9 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5432 | 5619 | }; |
| 5433 | 5620 | node = &and_node.base; |
| 5434 | 5621 | }, |
| 5435 | | .Lte => { |
| 5622 | .AngleBracketLeftEqual => { |
| 5436 | 5623 | const op_token = try appendToken(c, .AngleBracketLeftEqual, "<="); |
| 5437 | | const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5624 | const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5438 | 5625 | const and_node = try c.a().create(ast.Node.InfixOp); |
| 5439 | 5626 | and_node.* = .{ |
| 5440 | 5627 | .op_token = op_token, |
| ... | ... | @@ -5446,14 +5633,15 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5446 | 5633 | }, |
| 5447 | 5634 | .LBrace => { |
| 5448 | 5635 | const arr_node = try transCreateNodeArrayAccess(c, node); |
| 5449 | | arr_node.op.ArrayAccess = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5636 | arr_node.op.ArrayAccess = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5450 | 5637 | arr_node.rtoken = try appendToken(c, .RBrace, "]"); |
| 5451 | 5638 | node = &arr_node.base; |
| 5452 | 5639 | if (it.next().?.id != .RBrace) { |
| 5640 | const first_tok = it.list.at(0); |
| 5453 | 5641 | try failDecl( |
| 5454 | 5642 | c, |
| 5455 | 5643 | source_loc, |
| 5456 | | it.list.at(0).*.bytes, |
| 5644 | source[first_tok.start..first_tok.end], |
| 5457 | 5645 | "unable to translate C expr: expected ']'", |
| 5458 | 5646 | .{}, |
| 5459 | 5647 | ); |
| ... | ... | @@ -5463,7 +5651,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5463 | 5651 | .LParen => { |
| 5464 | 5652 | const call_node = try transCreateNodeFnCall(c, node); |
| 5465 | 5653 | while (true) { |
| 5466 | | const arg = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5654 | const arg = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5467 | 5655 | try call_node.op.Call.params.push(arg); |
| 5468 | 5656 | const next = it.next().?; |
| 5469 | 5657 | if (next.id == .Comma) |
| ... | ... | @@ -5471,10 +5659,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5471 | 5659 | else if (next.id == .RParen) |
| 5472 | 5660 | break |
| 5473 | 5661 | else { |
| 5662 | const first_tok = it.list.at(0); |
| 5474 | 5663 | try failDecl( |
| 5475 | 5664 | c, |
| 5476 | 5665 | source_loc, |
| 5477 | | it.list.at(0).*.bytes, |
| 5666 | source[first_tok.start..first_tok.end], |
| 5478 | 5667 | "unable to translate C expr: expected ',' or ')'", |
| 5479 | 5668 | .{}, |
| 5480 | 5669 | ); |
| ... | ... | @@ -5492,32 +5681,32 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig |
| 5492 | 5681 | } |
| 5493 | 5682 | } |
| 5494 | 5683 | |
| 5495 | | fn parseCPrefixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5684 | fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 5496 | 5685 | const op_tok = it.next().?; |
| 5497 | 5686 | |
| 5498 | 5687 | switch (op_tok.id) { |
| 5499 | 5688 | .Bang => { |
| 5500 | 5689 | const node = try transCreateNodePrefixOp(c, .BoolNot, .Bang, "!"); |
| 5501 | | node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5690 | node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5502 | 5691 | return &node.base; |
| 5503 | 5692 | }, |
| 5504 | 5693 | .Minus => { |
| 5505 | 5694 | const node = try transCreateNodePrefixOp(c, .Negation, .Minus, "-"); |
| 5506 | | node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5695 | node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5507 | 5696 | return &node.base; |
| 5508 | 5697 | }, |
| 5509 | 5698 | .Tilde => { |
| 5510 | 5699 | const node = try transCreateNodePrefixOp(c, .BitNot, .Tilde, "~"); |
| 5511 | | node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5700 | node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5512 | 5701 | return &node.base; |
| 5513 | 5702 | }, |
| 5514 | 5703 | .Asterisk => { |
| 5515 | | const prefix_op_expr = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 5704 | const prefix_op_expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 5516 | 5705 | return try transCreateNodePtrDeref(c, prefix_op_expr); |
| 5517 | 5706 | }, |
| 5518 | 5707 | else => { |
| 5519 | 5708 | _ = it.prev(); |
| 5520 | | return try parseCSuffixOpExpr(c, it, source_loc, scope); |
| 5709 | return try parseCSuffixOpExpr(c, it, source, source_loc, scope); |
| 5521 | 5710 | }, |
| 5522 | 5711 | } |
| 5523 | 5712 | } |