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