| author | |
| committer | |
| log | 00878a15d703a668970c7869276d33b21464714a |
| tree | d84e68f83d2b484e04494e3b36d76a6beb34e443 |
| parent | f25182f46dd672eb5b10533c67ed462a3e5df999 |
| signature |
5 files changed, 202 insertions(+), 192 deletions(-)
lib/std/zig/ast.zig+16-11| ... | @@ -137,7 +137,6 @@ pub const Error = union(enum) { | ... | @@ -137,7 +137,6 @@ pub const Error = union(enum) { |
| 137 | ExpectedCallOrFnProto: ExpectedCallOrFnProto, | 137 | ExpectedCallOrFnProto: ExpectedCallOrFnProto, |
| 138 | ExpectedSliceOrRBracket: ExpectedSliceOrRBracket, | 138 | ExpectedSliceOrRBracket: ExpectedSliceOrRBracket, |
| 139 | ExtraAlignQualifier: ExtraAlignQualifier, | 139 | ExtraAlignQualifier: ExtraAlignQualifier, |
| 140 | ExtraNullQualifier: ExtraNullQualifier, | ||
| 141 | ExtraConstQualifier: ExtraConstQualifier, | 140 | ExtraConstQualifier: ExtraConstQualifier, |
| 142 | ExtraVolatileQualifier: ExtraVolatileQualifier, | 141 | ExtraVolatileQualifier: ExtraVolatileQualifier, |
| 143 | ExtraAllowZeroQualifier: ExtraAllowZeroQualifier, | 142 | ExtraAllowZeroQualifier: ExtraAllowZeroQualifier, |
| ... | @@ -185,7 +184,6 @@ pub const Error = union(enum) { | ... | @@ -185,7 +184,6 @@ pub const Error = union(enum) { |
| 185 | .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), | 184 | .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), |
| 186 | .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), | 185 | .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), |
| 187 | .ExtraAlignQualifier => |*x| return x.render(tokens, stream), | 186 | .ExtraAlignQualifier => |*x| return x.render(tokens, stream), |
| 188 | .ExtraNullQualifier => |*x| return x.render(tokens, stream), | ||
| 189 | .ExtraConstQualifier => |*x| return x.render(tokens, stream), | 187 | .ExtraConstQualifier => |*x| return x.render(tokens, stream), |
| 190 | .ExtraVolatileQualifier => |*x| return x.render(tokens, stream), | 188 | .ExtraVolatileQualifier => |*x| return x.render(tokens, stream), |
| 191 | .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), | 189 | .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), |
| ... | @@ -235,7 +233,6 @@ pub const Error = union(enum) { | ... | @@ -235,7 +233,6 @@ pub const Error = union(enum) { |
| 235 | .ExpectedCallOrFnProto => |x| return x.node.firstToken(), | 233 | .ExpectedCallOrFnProto => |x| return x.node.firstToken(), |
| 236 | .ExpectedSliceOrRBracket => |x| return x.token, | 234 | .ExpectedSliceOrRBracket => |x| return x.token, |
| 237 | .ExtraAlignQualifier => |x| return x.token, | 235 | .ExtraAlignQualifier => |x| return x.token, |
| 238 | .ExtraNullQualifier => |x| return x.token, | ||
| 239 | .ExtraConstQualifier => |x| return x.token, | 236 | .ExtraConstQualifier => |x| return x.token, |
| 240 | .ExtraVolatileQualifier => |x| return x.token, | 237 | .ExtraVolatileQualifier => |x| return x.token, |
| 241 | .ExtraAllowZeroQualifier => |x| return x.token, | 238 | .ExtraAllowZeroQualifier => |x| return x.token, |
| ... | @@ -296,7 +293,6 @@ pub const Error = union(enum) { | ... | @@ -296,7 +293,6 @@ pub const Error = union(enum) { |
| 296 | pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub"); | 293 | pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub"); |
| 297 | pub const UnattachedDocComment = SimpleError("Unattached documentation comment"); | 294 | pub const UnattachedDocComment = SimpleError("Unattached documentation comment"); |
| 298 | pub const ExtraAlignQualifier = SimpleError("Extra align qualifier"); | 295 | pub const ExtraAlignQualifier = SimpleError("Extra align qualifier"); |
| 299 | pub const ExtraNullQualifier = SimpleError("Extra null qualifier"); | ||
| 300 | pub const ExtraConstQualifier = SimpleError("Extra const qualifier"); | 296 | pub const ExtraConstQualifier = SimpleError("Extra const qualifier"); |
| 301 | pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier"); | 297 | pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier"); |
| 302 | pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); | 298 | pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); |
| ... | @@ -1535,7 +1531,7 @@ pub const Node = struct { | ... | @@ -1535,7 +1531,7 @@ pub const Node = struct { |
| 1535 | }; | 1531 | }; |
| 1536 | 1532 | ||
| 1537 | pub const PrefixOp = struct { | 1533 | pub const PrefixOp = struct { |
| 1538 | base: Node, | 1534 | base: Node = Node{ .id = .PrefixOp }, |
| 1539 | op_token: TokenIndex, | 1535 | op_token: TokenIndex, |
| 1540 | op: Op, | 1536 | op: Op, |
| 1541 | rhs: *Node, | 1537 | rhs: *Node, |
| ... | @@ -1558,15 +1554,15 @@ pub const Node = struct { | ... | @@ -1558,15 +1554,15 @@ pub const Node = struct { |
| 1558 | 1554 | ||
| 1559 | pub const ArrayInfo = struct { | 1555 | pub const ArrayInfo = struct { |
| 1560 | len_expr: *Node, | 1556 | len_expr: *Node, |
| 1561 | null_token: ?TokenIndex, | 1557 | sentinel: ?*Node, |
| 1562 | }; | 1558 | }; |
| 1563 | 1559 | ||
| 1564 | pub const PtrInfo = struct { | 1560 | pub const PtrInfo = struct { |
| 1565 | allowzero_token: ?TokenIndex, | 1561 | allowzero_token: ?TokenIndex = null, |
| 1566 | align_info: ?Align, | 1562 | align_info: ?Align = null, |
| 1567 | const_token: ?TokenIndex, | 1563 | const_token: ?TokenIndex = null, |
| 1568 | volatile_token: ?TokenIndex, | 1564 | volatile_token: ?TokenIndex = null, |
| 1569 | null_token: ?TokenIndex, | 1565 | sentinel: ?*Node = null, |
| 1570 | 1566 | ||
| 1571 | pub const Align = struct { | 1567 | pub const Align = struct { |
| 1572 | node: *Node, | 1568 | node: *Node, |
| ... | @@ -1585,6 +1581,11 @@ pub const Node = struct { | ... | @@ -1585,6 +1581,11 @@ pub const Node = struct { |
| 1585 | switch (self.op) { | 1581 | switch (self.op) { |
| 1586 | // TODO https://github.com/ziglang/zig/issues/1107 | 1582 | // TODO https://github.com/ziglang/zig/issues/1107 |
| 1587 | Op.SliceType => |addr_of_info| { | 1583 | Op.SliceType => |addr_of_info| { |
| 1584 | if (addr_of_info.sentinel) |sentinel| { | ||
| 1585 | if (i < 1) return sentinel; | ||
| 1586 | i -= 1; | ||
| 1587 | } | ||
| 1588 | |||
| 1588 | if (addr_of_info.align_info) |align_info| { | 1589 | if (addr_of_info.align_info) |align_info| { |
| 1589 | if (i < 1) return align_info.node; | 1590 | if (i < 1) return align_info.node; |
| 1590 | i -= 1; | 1591 | i -= 1; |
| ... | @@ -1601,6 +1602,10 @@ pub const Node = struct { | ... | @@ -1601,6 +1602,10 @@ pub const Node = struct { |
| 1601 | Op.ArrayType => |array_info| { | 1602 | Op.ArrayType => |array_info| { |
| 1602 | if (i < 1) return array_info.len_expr; | 1603 | if (i < 1) return array_info.len_expr; |
| 1603 | i -= 1; | 1604 | i -= 1; |
| 1605 | if (array_info.sentinel) |sentinel| { | ||
| 1606 | if (i < 1) return sentinel; | ||
| 1607 | i -= 1; | ||
| 1608 | } | ||
| 1604 | }, | 1609 | }, |
| 1605 | 1610 | ||
| 1606 | Op.AddressOf, | 1611 | Op.AddressOf, |
lib/std/zig/parse.zig+127-109| ... | @@ -2246,73 +2246,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -2246,73 +2246,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2246 | return &node.base; | 2246 | return &node.base; |
| 2247 | } | 2247 | } |
| 2248 | 2248 | ||
| 2249 | if (try parseArrayTypeStart(arena, it, tree)) |node| { | ||
| 2250 | switch (node.cast(Node.PrefixOp).?.op) { | ||
| 2251 | .ArrayType => {}, | ||
| 2252 | .SliceType => |*slice_type| { | ||
| 2253 | // Collect pointer qualifiers in any order, but disallow duplicates | ||
| 2254 | while (true) { | ||
| 2255 | if (eatToken(it, .Keyword_null)) |null_token| { | ||
| 2256 | if (slice_type.null_token != null) { | ||
| 2257 | try tree.errors.push(AstError{ | ||
| 2258 | .ExtraNullQualifier = AstError.ExtraNullQualifier{ .token = it.index }, | ||
| 2259 | }); | ||
| 2260 | return error.ParseError; | ||
| 2261 | } | ||
| 2262 | slice_type.null_token = null_token; | ||
| 2263 | continue; | ||
| 2264 | } | ||
| 2265 | if (try parseByteAlign(arena, it, tree)) |align_expr| { | ||
| 2266 | if (slice_type.align_info != null) { | ||
| 2267 | try tree.errors.push(AstError{ | ||
| 2268 | .ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index }, | ||
| 2269 | }); | ||
| 2270 | return error.ParseError; | ||
| 2271 | } | ||
| 2272 | slice_type.align_info = Node.PrefixOp.PtrInfo.Align{ | ||
| 2273 | .node = align_expr, | ||
| 2274 | .bit_range = null, | ||
| 2275 | }; | ||
| 2276 | continue; | ||
| 2277 | } | ||
| 2278 | if (eatToken(it, .Keyword_const)) |const_token| { | ||
| 2279 | if (slice_type.const_token != null) { | ||
| 2280 | try tree.errors.push(AstError{ | ||
| 2281 | .ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index }, | ||
| 2282 | }); | ||
| 2283 | return error.ParseError; | ||
| 2284 | } | ||
| 2285 | slice_type.const_token = const_token; | ||
| 2286 | continue; | ||
| 2287 | } | ||
| 2288 | if (eatToken(it, .Keyword_volatile)) |volatile_token| { | ||
| 2289 | if (slice_type.volatile_token != null) { | ||
| 2290 | try tree.errors.push(AstError{ | ||
| 2291 | .ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index }, | ||
| 2292 | }); | ||
| 2293 | return error.ParseError; | ||
| 2294 | } | ||
| 2295 | slice_type.volatile_token = volatile_token; | ||
| 2296 | continue; | ||
| 2297 | } | ||
| 2298 | if (eatToken(it, .Keyword_allowzero)) |allowzero_token| { | ||
| 2299 | if (slice_type.allowzero_token != null) { | ||
| 2300 | try tree.errors.push(AstError{ | ||
| 2301 | .ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index }, | ||
| 2302 | }); | ||
| 2303 | return error.ParseError; | ||
| 2304 | } | ||
| 2305 | slice_type.allowzero_token = allowzero_token; | ||
| 2306 | continue; | ||
| 2307 | } | ||
| 2308 | break; | ||
| 2309 | } | ||
| 2310 | }, | ||
| 2311 | else => unreachable, | ||
| 2312 | } | ||
| 2313 | return node; | ||
| 2314 | } | ||
| 2315 | |||
| 2316 | if (try parsePtrTypeStart(arena, it, tree)) |node| { | 2249 | if (try parsePtrTypeStart(arena, it, tree)) |node| { |
| 2317 | // If the token encountered was **, there will be two nodes instead of one. | 2250 | // If the token encountered was **, there will be two nodes instead of one. |
| 2318 | // The attributes should be applied to the rightmost operator. | 2251 | // The attributes should be applied to the rightmost operator. |
| ... | @@ -2323,10 +2256,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -2323,10 +2256,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2323 | &prefix_op.op.PtrType; | 2256 | &prefix_op.op.PtrType; |
| 2324 | 2257 | ||
| 2325 | while (true) { | 2258 | while (true) { |
| 2326 | if (eatToken(it, .Keyword_null)) |null_token| { | ||
| 2327 | ptr_info.null_token = null_token; | ||
| 2328 | continue; | ||
| 2329 | } | ||
| 2330 | if (eatToken(it, .Keyword_align)) |align_token| { | 2259 | if (eatToken(it, .Keyword_align)) |align_token| { |
| 2331 | const lparen = try expectToken(it, tree, .LParen); | 2260 | const lparen = try expectToken(it, tree, .LParen); |
| 2332 | const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{ | 2261 | const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{ |
| ... | @@ -2375,6 +2304,63 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -2375,6 +2304,63 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2375 | return node; | 2304 | return node; |
| 2376 | } | 2305 | } |
| 2377 | 2306 | ||
| 2307 | if (try parseArrayTypeStart(arena, it, tree)) |node| { | ||
| 2308 | switch (node.cast(Node.PrefixOp).?.op) { | ||
| 2309 | .ArrayType => {}, | ||
| 2310 | .SliceType => |*slice_type| { | ||
| 2311 | // Collect pointer qualifiers in any order, but disallow duplicates | ||
| 2312 | while (true) { | ||
| 2313 | if (try parseByteAlign(arena, it, tree)) |align_expr| { | ||
| 2314 | if (slice_type.align_info != null) { | ||
| 2315 | try tree.errors.push(AstError{ | ||
| 2316 | .ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index }, | ||
| 2317 | }); | ||
| 2318 | return error.ParseError; | ||
| 2319 | } | ||
| 2320 | slice_type.align_info = Node.PrefixOp.PtrInfo.Align{ | ||
| 2321 | .node = align_expr, | ||
| 2322 | .bit_range = null, | ||
| 2323 | }; | ||
| 2324 | continue; | ||
| 2325 | } | ||
| 2326 | if (eatToken(it, .Keyword_const)) |const_token| { | ||
| 2327 | if (slice_type.const_token != null) { | ||
| 2328 | try tree.errors.push(AstError{ | ||
| 2329 | .ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index }, | ||
| 2330 | }); | ||
| 2331 | return error.ParseError; | ||
| 2332 | } | ||
| 2333 | slice_type.const_token = const_token; | ||
| 2334 | continue; | ||
| 2335 | } | ||
| 2336 | if (eatToken(it, .Keyword_volatile)) |volatile_token| { | ||
| 2337 | if (slice_type.volatile_token != null) { | ||
| 2338 | try tree.errors.push(AstError{ | ||
| 2339 | .ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index }, | ||
| 2340 | }); | ||
| 2341 | return error.ParseError; | ||
| 2342 | } | ||
| 2343 | slice_type.volatile_token = volatile_token; | ||
| 2344 | continue; | ||
| 2345 | } | ||
| 2346 | if (eatToken(it, .Keyword_allowzero)) |allowzero_token| { | ||
| 2347 | if (slice_type.allowzero_token != null) { | ||
| 2348 | try tree.errors.push(AstError{ | ||
| 2349 | .ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index }, | ||
| 2350 | }); | ||
| 2351 | return error.ParseError; | ||
| 2352 | } | ||
| 2353 | slice_type.allowzero_token = allowzero_token; | ||
| 2354 | continue; | ||
| 2355 | } | ||
| 2356 | break; | ||
| 2357 | } | ||
| 2358 | }, | ||
| 2359 | else => unreachable, | ||
| 2360 | } | ||
| 2361 | return node; | ||
| 2362 | } | ||
| 2363 | |||
| 2378 | return null; | 2364 | return null; |
| 2379 | } | 2365 | } |
| 2380 | 2366 | ||
| ... | @@ -2473,14 +2459,19 @@ const AnnotatedParamList = struct { | ... | @@ -2473,14 +2459,19 @@ const AnnotatedParamList = struct { |
| 2473 | fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 2459 | fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2474 | const lbracket = eatToken(it, .LBracket) orelse return null; | 2460 | const lbracket = eatToken(it, .LBracket) orelse return null; |
| 2475 | const expr = try parseExpr(arena, it, tree); | 2461 | const expr = try parseExpr(arena, it, tree); |
| 2462 | const sentinel = if (eatToken(it, .Colon)) |_| | ||
| 2463 | try expectNode(arena, it, tree, parseExpr, AstError{ | ||
| 2464 | .ExpectedExpr = .{ .token = it.index }, | ||
| 2465 | }) | ||
| 2466 | else | ||
| 2467 | null; | ||
| 2476 | const rbracket = try expectToken(it, tree, .RBracket); | 2468 | const rbracket = try expectToken(it, tree, .RBracket); |
| 2477 | const null_token = eatToken(it, .Keyword_null); | ||
| 2478 | 2469 | ||
| 2479 | const op = if (expr) |len_expr| | 2470 | const op = if (expr) |len_expr| |
| 2480 | Node.PrefixOp.Op{ | 2471 | Node.PrefixOp.Op{ |
| 2481 | .ArrayType = .{ | 2472 | .ArrayType = .{ |
| 2482 | .len_expr = len_expr, | 2473 | .len_expr = len_expr, |
| 2483 | .null_token = null_token, | 2474 | .sentinel = sentinel, |
| 2484 | }, | 2475 | }, |
| 2485 | } | 2476 | } |
| 2486 | else | 2477 | else |
| ... | @@ -2490,7 +2481,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No | ... | @@ -2490,7 +2481,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 2490 | .align_info = null, | 2481 | .align_info = null, |
| 2491 | .const_token = null, | 2482 | .const_token = null, |
| 2492 | .volatile_token = null, | 2483 | .volatile_token = null, |
| 2493 | .null_token = null, | 2484 | .sentinel = sentinel, |
| 2494 | }, | 2485 | }, |
| 2495 | }; | 2486 | }; |
| 2496 | 2487 | ||
| ... | @@ -2510,49 +2501,76 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No | ... | @@ -2510,49 +2501,76 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 2510 | /// / PTRUNKNOWN | 2501 | /// / PTRUNKNOWN |
| 2511 | /// / PTRC | 2502 | /// / PTRC |
| 2512 | fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 2503 | fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2513 | const token = eatAnnotatedToken(it, .Asterisk) orelse | 2504 | if (eatToken(it, .Asterisk)) |asterisk| { |
| 2514 | eatAnnotatedToken(it, .AsteriskAsterisk) orelse | 2505 | const sentinel = if (eatToken(it, .Colon)) |_| |
| 2515 | eatAnnotatedToken(it, .BracketStarBracket) orelse | 2506 | try expectNode(arena, it, tree, parseExpr, AstError{ |
| 2516 | eatAnnotatedToken(it, .BracketStarCBracket) orelse | 2507 | .ExpectedExpr = .{ .token = it.index }, |
| 2517 | return null; | 2508 | }) |
| 2509 | else | ||
| 2510 | null; | ||
| 2511 | const node = try arena.create(Node.PrefixOp); | ||
| 2512 | node.* = .{ | ||
| 2513 | .op_token = asterisk, | ||
| 2514 | .op = .{ .PtrType = .{ .sentinel = sentinel } }, | ||
| 2515 | .rhs = undefined, // set by caller | ||
| 2516 | }; | ||
| 2517 | return &node.base; | ||
| 2518 | } | ||
| 2518 | 2519 | ||
| 2519 | const node = try arena.create(Node.PrefixOp); | 2520 | if (eatToken(it, .AsteriskAsterisk)) |double_asterisk| { |
| 2520 | node.* = Node.PrefixOp{ | 2521 | const node = try arena.create(Node.PrefixOp); |
| 2521 | .base = Node{ .id = .PrefixOp }, | 2522 | node.* = Node.PrefixOp{ |
| 2522 | .op_token = token.index, | 2523 | .op_token = double_asterisk, |
| 2523 | .op = Node.PrefixOp.Op{ | 2524 | .op = Node.PrefixOp.Op{ .PtrType = .{} }, |
| 2524 | .PtrType = Node.PrefixOp.PtrInfo{ | 2525 | .rhs = undefined, // set by caller |
| 2525 | .allowzero_token = null, | 2526 | }; |
| 2526 | .align_info = null, | ||
| 2527 | .const_token = null, | ||
| 2528 | .volatile_token = null, | ||
| 2529 | .null_token = null, | ||
| 2530 | }, | ||
| 2531 | }, | ||
| 2532 | .rhs = undefined, // set by caller | ||
| 2533 | }; | ||
| 2534 | 2527 | ||
| 2535 | // Special case for **, which is its own token | 2528 | // Special case for **, which is its own token |
| 2536 | if (token.ptr.id == .AsteriskAsterisk) { | ||
| 2537 | const child = try arena.create(Node.PrefixOp); | 2529 | const child = try arena.create(Node.PrefixOp); |
| 2538 | child.* = Node.PrefixOp{ | 2530 | child.* = Node.PrefixOp{ |
| 2539 | .base = Node{ .id = .PrefixOp }, | 2531 | .op_token = double_asterisk, |
| 2540 | .op_token = token.index, | 2532 | .op = Node.PrefixOp.Op{ .PtrType = .{} }, |
| 2541 | .op = Node.PrefixOp.Op{ | ||
| 2542 | .PtrType = Node.PrefixOp.PtrInfo{ | ||
| 2543 | .allowzero_token = null, | ||
| 2544 | .align_info = null, | ||
| 2545 | .const_token = null, | ||
| 2546 | .volatile_token = null, | ||
| 2547 | .null_token = null, | ||
| 2548 | }, | ||
| 2549 | }, | ||
| 2550 | .rhs = undefined, // set by caller | 2533 | .rhs = undefined, // set by caller |
| 2551 | }; | 2534 | }; |
| 2552 | node.rhs = &child.base; | 2535 | node.rhs = &child.base; |
| 2553 | } | ||
| 2554 | 2536 | ||
| 2555 | return &node.base; | 2537 | return &node.base; |
| 2538 | } | ||
| 2539 | if (eatToken(it, .LBracket)) |lbracket| { | ||
| 2540 | const asterisk = eatToken(it, .Asterisk) orelse { | ||
| 2541 | putBackToken(it, lbracket); | ||
| 2542 | return null; | ||
| 2543 | }; | ||
| 2544 | if (eatToken(it, .Identifier)) |ident| { | ||
| 2545 | if (!std.mem.eql(u8, tree.tokenSlice(ident), "c")) { | ||
| 2546 | putBackToken(it, ident); | ||
| 2547 | } else { | ||
| 2548 | _ = try expectToken(it, tree, .RBracket); | ||
| 2549 | const node = try arena.create(Node.PrefixOp); | ||
| 2550 | node.* = .{ | ||
| 2551 | .op_token = ident, | ||
| 2552 | .op = .{ .PtrType = .{} }, | ||
| 2553 | .rhs = undefined, // set by caller | ||
| 2554 | }; | ||
| 2555 | return &node.base; | ||
| 2556 | } | ||
| 2557 | } | ||
| 2558 | const sentinel = if (eatToken(it, .Colon)) |_| | ||
| 2559 | try expectNode(arena, it, tree, parseExpr, AstError{ | ||
| 2560 | .ExpectedExpr = .{ .token = it.index }, | ||
| 2561 | }) | ||
| 2562 | else | ||
| 2563 | null; | ||
| 2564 | _ = try expectToken(it, tree, .RBracket); | ||
| 2565 | const node = try arena.create(Node.PrefixOp); | ||
| 2566 | node.* = .{ | ||
| 2567 | .op_token = lbracket, | ||
| 2568 | .op = .{ .PtrType = .{ .sentinel = sentinel } }, | ||
| 2569 | .rhs = undefined, // set by caller | ||
| 2570 | }; | ||
| 2571 | return &node.base; | ||
| 2572 | } | ||
| 2573 | return null; | ||
| 2556 | } | 2574 | } |
| 2557 | 2575 | ||
| 2558 | /// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE | 2576 | /// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE |
lib/std/zig/render.zig+29-11| ... | @@ -418,13 +418,26 @@ fn renderExpression( | ... | @@ -418,13 +418,26 @@ fn renderExpression( |
| 418 | 418 | ||
| 419 | switch (prefix_op_node.op) { | 419 | switch (prefix_op_node.op) { |
| 420 | ast.Node.PrefixOp.Op.PtrType => |ptr_info| { | 420 | ast.Node.PrefixOp.Op.PtrType => |ptr_info| { |
| 421 | const star_offset = switch (tree.tokens.at(prefix_op_node.op_token).id) { | 421 | const op_tok_id = tree.tokens.at(prefix_op_node.op_token).id; |
| 422 | Token.Id.AsteriskAsterisk => @as(usize, 1), | 422 | switch (op_tok_id) { |
| 423 | else => @as(usize, 0), | 423 | .Asterisk, .AsteriskAsterisk => try stream.writeByte('*'), |
| 424 | }; | 424 | .Identifier => try stream.write("[*c]"), |
| 425 | try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // * | 425 | .LBracket => try stream.write("[*"), |
| 426 | if (ptr_info.null_token) |null_token| { | 426 | else => unreachable, |
| 427 | try renderToken(tree, stream, null_token, indent, start_col, Space.Space); // null | 427 | } |
| 428 | if (ptr_info.sentinel) |sentinel| { | ||
| 429 | const colon_token = tree.prevToken(sentinel.firstToken()); | ||
| 430 | try renderToken(tree, stream, colon_token, indent, start_col, Space.None); // : | ||
| 431 | const sentinel_space = switch (op_tok_id) { | ||
| 432 | .LBracket => Space.None, | ||
| 433 | else => Space.Space, | ||
| 434 | }; | ||
| 435 | try renderExpression(allocator, stream, tree, indent, start_col, sentinel, sentinel_space); | ||
| 436 | } | ||
| 437 | switch (op_tok_id) { | ||
| 438 | .Asterisk, .AsteriskAsterisk, .Identifier => {}, | ||
| 439 | .LBracket => try stream.writeByte(']'), | ||
| 440 | else => unreachable, | ||
| 428 | } | 441 | } |
| 429 | if (ptr_info.allowzero_token) |allowzero_token| { | 442 | if (ptr_info.allowzero_token) |allowzero_token| { |
| 430 | try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero | 443 | try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero |
| ... | @@ -504,7 +517,10 @@ fn renderExpression( | ... | @@ -504,7 +517,10 @@ fn renderExpression( |
| 504 | 517 | ||
| 505 | ast.Node.PrefixOp.Op.ArrayType => |array_info| { | 518 | ast.Node.PrefixOp.Op.ArrayType => |array_info| { |
| 506 | const lbracket = prefix_op_node.op_token; | 519 | const lbracket = prefix_op_node.op_token; |
| 507 | const rbracket = tree.nextToken(array_info.len_expr.lastToken()); | 520 | const rbracket = tree.nextToken(if (array_info.sentinel) |sentinel| |
| 521 | sentinel.lastToken() | ||
| 522 | else | ||
| 523 | array_info.len_expr.lastToken()); | ||
| 508 | 524 | ||
| 509 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ | 525 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ |
| 510 | 526 | ||
| ... | @@ -519,10 +535,12 @@ fn renderExpression( | ... | @@ -519,10 +535,12 @@ fn renderExpression( |
| 519 | if (ends_with_comment or starts_with_comment) { | 535 | if (ends_with_comment or starts_with_comment) { |
| 520 | try stream.writeByteNTimes(' ', indent); | 536 | try stream.writeByteNTimes(' ', indent); |
| 521 | } | 537 | } |
| 522 | try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ] | 538 | if (array_info.sentinel) |sentinel| { |
| 523 | if (array_info.null_token) |null_token| { | 539 | const colon_token = tree.prevToken(sentinel.firstToken()); |
| 524 | try renderToken(tree, stream, null_token, indent, start_col, Space.Space); // null | 540 | try renderToken(tree, stream, colon_token, indent, start_col, Space.None); // : |
| 541 | try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None); | ||
| 525 | } | 542 | } |
| 543 | try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ] | ||
| 526 | }, | 544 | }, |
| 527 | ast.Node.PrefixOp.Op.BitNot, | 545 | ast.Node.PrefixOp.Op.BitNot, |
| 528 | ast.Node.PrefixOp.Op.BoolNot, | 546 | ast.Node.PrefixOp.Op.BoolNot, |
lib/std/zig/tokenizer.zig+10-52| ... | @@ -143,8 +143,6 @@ pub const Token = struct { | ... | @@ -143,8 +143,6 @@ pub const Token = struct { |
| 143 | LineComment, | 143 | LineComment, |
| 144 | DocComment, | 144 | DocComment, |
| 145 | ContainerDocComment, | 145 | ContainerDocComment, |
| 146 | BracketStarBracket, | ||
| 147 | BracketStarCBracket, | ||
| 148 | ShebangLine, | 146 | ShebangLine, |
| 149 | Keyword_align, | 147 | Keyword_align, |
| 150 | Keyword_allowzero, | 148 | Keyword_allowzero, |
| ... | @@ -269,8 +267,6 @@ pub const Token = struct { | ... | @@ -269,8 +267,6 @@ pub const Token = struct { |
| 269 | .AngleBracketAngleBracketRight => ">>", | 267 | .AngleBracketAngleBracketRight => ">>", |
| 270 | .AngleBracketAngleBracketRightEqual => ">>=", | 268 | .AngleBracketAngleBracketRightEqual => ">>=", |
| 271 | .Tilde => "~", | 269 | .Tilde => "~", |
| 272 | .BracketStarBracket => "[*]", | ||
| 273 | .BracketStarCBracket => "[*c]", | ||
| 274 | .Keyword_align => "align", | 270 | .Keyword_align => "align", |
| 275 | .Keyword_allowzero => "allowzero", | 271 | .Keyword_allowzero => "allowzero", |
| 276 | .Keyword_and => "and", | 272 | .Keyword_and => "and", |
| ... | @@ -400,9 +396,6 @@ pub const Tokenizer = struct { | ... | @@ -400,9 +396,6 @@ pub const Tokenizer = struct { |
| 400 | Period, | 396 | Period, |
| 401 | Period2, | 397 | Period2, |
| 402 | SawAtSign, | 398 | SawAtSign, |
| 403 | LBracket, | ||
| 404 | LBracketStar, | ||
| 405 | LBracketStarC, | ||
| 406 | }; | 399 | }; |
| 407 | 400 | ||
| 408 | pub fn next(self: *Tokenizer) Token { | 401 | pub fn next(self: *Tokenizer) Token { |
| ... | @@ -460,7 +453,9 @@ pub const Tokenizer = struct { | ... | @@ -460,7 +453,9 @@ pub const Tokenizer = struct { |
| 460 | break; | 453 | break; |
| 461 | }, | 454 | }, |
| 462 | '[' => { | 455 | '[' => { |
| 463 | state = State.LBracket; | 456 | result.id = .LBracket; |
| 457 | self.index += 1; | ||
| 458 | break; | ||
| 464 | }, | 459 | }, |
| 465 | ']' => { | 460 | ']' => { |
| 466 | result.id = Token.Id.RBracket; | 461 | result.id = Token.Id.RBracket; |
| ... | @@ -564,43 +559,6 @@ pub const Tokenizer = struct { | ... | @@ -564,43 +559,6 @@ pub const Tokenizer = struct { |
| 564 | }, | 559 | }, |
| 565 | }, | 560 | }, |
| 566 | 561 | ||
| 567 | State.LBracket => switch (c) { | ||
| 568 | '*' => { | ||
| 569 | state = State.LBracketStar; | ||
| 570 | }, | ||
| 571 | else => { | ||
| 572 | result.id = Token.Id.LBracket; | ||
| 573 | break; | ||
| 574 | }, | ||
| 575 | }, | ||
| 576 | |||
| 577 | State.LBracketStar => switch (c) { | ||
| 578 | 'c' => { | ||
| 579 | state = State.LBracketStarC; | ||
| 580 | }, | ||
| 581 | ']' => { | ||
| 582 | result.id = Token.Id.BracketStarBracket; | ||
| 583 | self.index += 1; | ||
| 584 | break; | ||
| 585 | }, | ||
| 586 | else => { | ||
| 587 | result.id = Token.Id.Invalid; | ||
| 588 | break; | ||
| 589 | }, | ||
| 590 | }, | ||
| 591 | |||
| 592 | State.LBracketStarC => switch (c) { | ||
| 593 | ']' => { | ||
| 594 | result.id = Token.Id.BracketStarCBracket; | ||
| 595 | self.index += 1; | ||
| 596 | break; | ||
| 597 | }, | ||
| 598 | else => { | ||
| 599 | result.id = Token.Id.Invalid; | ||
| 600 | break; | ||
| 601 | }, | ||
| 602 | }, | ||
| 603 | |||
| 604 | State.Ampersand => switch (c) { | 562 | State.Ampersand => switch (c) { |
| 605 | '&' => { | 563 | '&' => { |
| 606 | result.id = Token.Id.Invalid_ampersands; | 564 | result.id = Token.Id.Invalid_ampersands; |
| ... | @@ -1227,8 +1185,6 @@ pub const Tokenizer = struct { | ... | @@ -1227,8 +1185,6 @@ pub const Tokenizer = struct { |
| 1227 | State.CharLiteralEnd, | 1185 | State.CharLiteralEnd, |
| 1228 | State.CharLiteralUnicode, | 1186 | State.CharLiteralUnicode, |
| 1229 | State.StringLiteralBackslash, | 1187 | State.StringLiteralBackslash, |
| 1230 | State.LBracketStar, | ||
| 1231 | State.LBracketStarC, | ||
| 1232 | => { | 1188 | => { |
| 1233 | result.id = Token.Id.Invalid; | 1189 | result.id = Token.Id.Invalid; |
| 1234 | }, | 1190 | }, |
| ... | @@ -1245,9 +1201,6 @@ pub const Tokenizer = struct { | ... | @@ -1245,9 +1201,6 @@ pub const Tokenizer = struct { |
| 1245 | State.Slash => { | 1201 | State.Slash => { |
| 1246 | result.id = Token.Id.Slash; | 1202 | result.id = Token.Id.Slash; |
| 1247 | }, | 1203 | }, |
| 1248 | State.LBracket => { | ||
| 1249 | result.id = Token.Id.LBracket; | ||
| 1250 | }, | ||
| 1251 | State.Zero => { | 1204 | State.Zero => { |
| 1252 | result.id = Token.Id.IntegerLiteral; | 1205 | result.id = Token.Id.IntegerLiteral; |
| 1253 | }, | 1206 | }, |
| ... | @@ -1368,9 +1321,14 @@ test "tokenizer - unknown length pointer and then c pointer" { | ... | @@ -1368,9 +1321,14 @@ test "tokenizer - unknown length pointer and then c pointer" { |
| 1368 | \\[*]u8 | 1321 | \\[*]u8 |
| 1369 | \\[*c]u8 | 1322 | \\[*c]u8 |
| 1370 | , [_]Token.Id{ | 1323 | , [_]Token.Id{ |
| 1371 | Token.Id.BracketStarBracket, | 1324 | Token.Id.LBracket, |
| 1325 | Token.Id.Asterisk, | ||
| 1326 | Token.Id.RBracket, | ||
| 1327 | Token.Id.Identifier, | ||
| 1328 | Token.Id.LBracket, | ||
| 1329 | Token.Id.Asterisk, | ||
| 1372 | Token.Id.Identifier, | 1330 | Token.Id.Identifier, |
| 1373 | Token.Id.BracketStarCBracket, | 1331 | Token.Id.RBracket, |
| 1374 | Token.Id.Identifier, | 1332 | Token.Id.Identifier, |
| 1375 | }); | 1333 | }); |
| 1376 | } | 1334 | } |
src-self-hosted/translate_c.zig+20-9| ... | @@ -1105,19 +1105,32 @@ fn transCreateNodePtrType( | ... | @@ -1105,19 +1105,32 @@ fn transCreateNodePtrType( |
| 1105 | is_const: bool, | 1105 | is_const: bool, |
| 1106 | is_volatile: bool, | 1106 | is_volatile: bool, |
| 1107 | op_tok_id: std.zig.Token.Id, | 1107 | op_tok_id: std.zig.Token.Id, |
| 1108 | bytes: []const u8, | ||
| 1109 | ) !*ast.Node.PrefixOp { | 1108 | ) !*ast.Node.PrefixOp { |
| 1110 | const node = try c.a().create(ast.Node.PrefixOp); | 1109 | const node = try c.a().create(ast.Node.PrefixOp); |
| 1110 | const op_token = switch (op_tok_id) { | ||
| 1111 | .LBracket => blk: { | ||
| 1112 | const lbracket = try appendToken(c, .LBracket, "["); | ||
| 1113 | _ = try appendToken(c, .Asterisk, "*"); | ||
| 1114 | _ = try appendToken(c, .RBracket, "]"); | ||
| 1115 | break :blk lbracket; | ||
| 1116 | }, | ||
| 1117 | .Identifier => blk: { | ||
| 1118 | _ = try appendToken(c, .LBracket, "["); | ||
| 1119 | _ = try appendToken(c, .Asterisk, "*"); | ||
| 1120 | const c_ident = try appendToken(c, .Identifier, "c"); | ||
| 1121 | _ = try appendToken(c, .RBracket, "]"); | ||
| 1122 | break :blk c_ident; | ||
| 1123 | }, | ||
| 1124 | .Asterisk => try appendToken(c, .Asterisk, "*"), | ||
| 1125 | else => unreachable, | ||
| 1126 | }; | ||
| 1111 | node.* = ast.Node.PrefixOp{ | 1127 | node.* = ast.Node.PrefixOp{ |
| 1112 | .base = ast.Node{ .id = .PrefixOp }, | 1128 | .base = ast.Node{ .id = .PrefixOp }, |
| 1113 | .op_token = try appendToken(c, op_tok_id, bytes), | 1129 | .op_token = op_token, |
| 1114 | .op = ast.Node.PrefixOp.Op{ | 1130 | .op = ast.Node.PrefixOp.Op{ |
| 1115 | .PtrType = ast.Node.PrefixOp.PtrInfo{ | 1131 | .PtrType = .{ |
| 1116 | .allowzero_token = null, | ||
| 1117 | .align_info = null, | ||
| 1118 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, | 1132 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, |
| 1119 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, | 1133 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, |
| 1120 | .null_token = null, | ||
| 1121 | }, | 1134 | }, |
| 1122 | }, | 1135 | }, |
| 1123 | .rhs = undefined, // translate and set afterward | 1136 | .rhs = undefined, // translate and set afterward |
| ... | @@ -1226,7 +1239,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1226,7 +1239,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1226 | ZigClangQualType_isConstQualified(child_qt), | 1239 | ZigClangQualType_isConstQualified(child_qt), |
| 1227 | ZigClangQualType_isVolatileQualified(child_qt), | 1240 | ZigClangQualType_isVolatileQualified(child_qt), |
| 1228 | .Asterisk, | 1241 | .Asterisk, |
| 1229 | "*", | ||
| 1230 | ); | 1242 | ); |
| 1231 | optional_node.rhs = &pointer_node.base; | 1243 | optional_node.rhs = &pointer_node.base; |
| 1232 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); | 1244 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); |
| ... | @@ -1236,8 +1248,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1236,8 +1248,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1236 | rp.c, | 1248 | rp.c, |
| 1237 | ZigClangQualType_isConstQualified(child_qt), | 1249 | ZigClangQualType_isConstQualified(child_qt), |
| 1238 | ZigClangQualType_isVolatileQualified(child_qt), | 1250 | ZigClangQualType_isVolatileQualified(child_qt), |
| 1239 | .BracketStarCBracket, | 1251 | .Identifier, |
| 1240 | "[*c]", | ||
| 1241 | ); | 1252 | ); |
| 1242 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); | 1253 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); |
| 1243 | return &pointer_node.base; | 1254 | return &pointer_node.base; |