Commit e4d0b46c0c
Changed files (2)
std
std/zig/ast.zig
@@ -20,9 +20,11 @@ pub const Node = struct {
FnProto,
ParamDecl,
Block,
+ Payload,
Switch,
SwitchCase,
SwitchElse,
+ While,
InfixOp,
PrefixOp,
SuffixOp,
@@ -58,9 +60,11 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
+ Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index),
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
+ Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
@@ -97,9 +101,11 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
+ Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(),
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
+ Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
@@ -136,9 +142,11 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
+ Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(),
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
- Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
+ Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
+ Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
@@ -545,6 +553,31 @@ pub const NodeBlock = struct {
}
};
+pub const NodePayload = struct {
+ base: Node,
+ lpipe: Token,
+ is_ptr: bool,
+ symbol: &NodeIdentifier,
+ rpipe: Token,
+
+ pub fn iterate(self: &NodePayload, index: usize) ?&Node {
+ var i = index;
+
+ if (i < 1) return &self.symbol.base;
+ i -= 1;
+
+ return null;
+ }
+
+ pub fn firstToken(self: &NodePayload) Token {
+ return self.lpipe;
+ }
+
+ pub fn lastToken(self: &NodePayload) Token {
+ return self.rpipe;
+ }
+};
+
pub const NodeSwitch = struct {
base: Node,
switch_token: Token,
@@ -576,22 +609,17 @@ pub const NodeSwitch = struct {
pub const NodeSwitchCase = struct {
base: Node,
items: ArrayList(&Node),
- capture: ?Capture,
+ payload: ?&Node,
expr: &Node,
- const Capture = struct {
- symbol: &NodeIdentifier,
- is_ptr: bool,
- };
-
pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
var i = index;
if (i < self.items.len) return self.items.at(i);
i -= self.items.len;
- if (self.capture) |capture| {
- if (i < 1) return &capture.base;
+ if (self.payload) |payload| {
+ if (i < 1) return payload;
i -= 1;
}
@@ -627,6 +655,66 @@ pub const NodeSwitchElse = struct {
}
};
+pub const NodeWhile = struct {
+ base: Node,
+ while_token: Token,
+ condition: &Node,
+ payload: ?&NodePayload,
+ continue_expr: ?&Node,
+ body: &Node,
+ @"else": ?Else,
+
+ const Else = struct {
+ capture: ?&NodeIdentifier,
+ body: &Node,
+ };
+
+
+ pub fn iterate(self: &NodeWhile, index: usize) ?&Node {
+ var i = index;
+
+ if (i < 1) return self.condition;
+ i -= 1;
+
+ if (self.payload) |payload| {
+ if (i < 1) return &payload.base;
+ i -= 1;
+ }
+
+ if (self.continue_expr) |continue_expr| {
+ if (i < 1) return continue_expr;
+ i -= 1;
+ }
+
+ if (i < 1) return self.body;
+ i -= 1;
+
+ if (self.@"else") |@"else"| {
+ if (@"else".capture) |capture| {
+ if (i < 1) return &capture.base;
+ i -= 1;
+ }
+
+ if (i < 1) return @"else".body;
+ i -= 1;
+ }
+
+ return null;
+ }
+
+ pub fn firstToken(self: &NodeWhile) Token {
+ return self.while_token;
+ }
+
+ pub fn lastToken(self: &NodeWhile) Token {
+ if (self.@"else") |@"else"| {
+ return @"else".body.lastToken();
+ }
+
+ return self.body.lastToken();
+ }
+};
+
pub const NodeInfixOp = struct {
base: Node,
op_token: Token,
@@ -661,7 +749,7 @@ pub const NodeInfixOp = struct {
BitXor,
BoolAnd,
BoolOr,
- Catch: ?&NodeIdentifier,
+ Catch: ?&Node,
Div,
EqualEqual,
ErrorUnion,
std/zig/parser.zig
@@ -104,6 +104,11 @@ pub const Parser = struct {
ptr: &Token,
};
+ const ElseCtx = struct {
+ payload: ?DestPtr,
+ body: DestPtr,
+ };
+
fn ListSave(comptime T: type) type {
return struct {
list: &ArrayList(T),
@@ -140,7 +145,7 @@ pub const Parser = struct {
FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
FieldListCommaOrEnd: &ast.NodeContainerDecl,
SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
- SwitchCaseCapture: &?ast.NodeSwitchCase.Capture,
+ Payload: DestPtr,
SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
SwitchCaseItem: &ArrayList(&ast.Node),
SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
@@ -635,9 +640,6 @@ pub const Parser = struct {
Token.Id.Keyword_await => {
@panic("TODO: await");
},
- Token.Id.Keyword_suspend => {
- @panic("TODO: suspend");
- },
else => {
self.putBackToken(token);
stack.append(State { .AssignmentExpressionBegin = dest_ptr }) catch unreachable;
@@ -705,21 +707,14 @@ pub const Parser = struct {
stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
-
- const next = self.getNextToken();
- if (next.id != Token.Id.Pipe) {
- self.putBackToken(next);
- continue;
- }
-
- node.op.Catch = try self.createIdentifier(arena, Token(undefined));
- try stack.append(State { .ExpectToken = Token.Id.Pipe });
try stack.append(State {
- .ExpectTokenSave = ExpectTokenSave {
- .id = Token.Id.Identifier,
- .ptr = &(??node.op.Catch).name_token
+ .Optional = RevertState {
+ .tokenizer = *self.tokenizer,
+ .parser = *self,
+ .ptr = &node.op.Catch,
}
});
+ try stack.append(State { .Payload = DestPtr { .NullableField = &node.op.Catch } });
continue;
},
Token.Id.QuestionMarkQuestionMark => {
@@ -1404,12 +1399,25 @@ pub const Parser = struct {
@panic("TODO: inline if");
},
Token.Id.Keyword_while => {
+ const node = try arena.create(ast.NodeWhile);
+ *node = ast.NodeWhile {
+ .base = self.initNode(ast.Node.Id.While),
+ .while_token = token,
+ .condition = undefined,
+ .payload = null,
+ .continue_expr = null,
+ .body = undefined,
+ .@"else" = null,
+ };
+ dest_ptr.store(&node.base);
+
@panic("TODO: inline while");
},
Token.Id.Keyword_for => {
@panic("TODO: inline for");
},
Token.Id.Keyword_switch => {
+ @breakpoint();
const node = try arena.create(ast.NodeSwitch);
*node = ast.NodeSwitch {
.base = self.initNode(ast.Node.Id.Switch),
@@ -1434,9 +1442,6 @@ pub const Parser = struct {
Token.Id.Keyword_comptime => {
@panic("TODO: inline comptime");
},
- Token.Id.Keyword_suspend => {
- @panic("TODO: inline suspend");
- },
else => {
try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
continue;
@@ -1547,13 +1552,21 @@ pub const Parser = struct {
*node = ast.NodeSwitchCase {
.base = self.initNode(ast.Node.Id.SwitchCase),
.items = ArrayList(&ast.Node).init(arena),
- .capture = null,
+ .payload = null,
.expr = undefined,
};
try list_state.list.append(node);
stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
- try stack.append(State { .SwitchCaseCapture = &node.capture });
+ try stack.append(State {
+ .Optional = RevertState {
+ .tokenizer = *self.tokenizer,
+ .parser = *self,
+ .ptr = &node.payload,
+ }
+ });
+ try stack.append(State { .Payload = DestPtr { .NullableField = &node.payload } });
+ try stack.append(State.Required);
const maybe_else = self.getNextToken();
if (maybe_else.id == Token.Id.Keyword_else) {
@@ -1572,12 +1585,8 @@ pub const Parser = struct {
}
},
- State.SwitchCaseCapture => |capture| {
- const token = self.getNextToken();
- if (token.id != Token.Id.Pipe) {
- self.putBackToken(token);
- continue;
- }
+ State.Payload => |dest_ptr| {
+ const lpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
const is_ptr = blk: {
const asterik = self.getNextToken();
@@ -1590,11 +1599,16 @@ pub const Parser = struct {
};
const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
- _ = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
- *capture = ast.NodeSwitchCase.Capture {
+ const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
+ const node = try arena.create(ast.NodePayload);
+ *node = ast.NodePayload {
+ .base = self.initNode(ast.Node.Id.Payload),
+ .lpipe = lpipe,
+ .is_ptr = is_ptr,
.symbol = try self.createIdentifier(arena, ident),
- .is_ptr = is_ptr
+ .rpipe = rpipe
};
+ dest_ptr.store(&node.base);
},
State.SwitchCaseItem => |case_items| {
@@ -1856,6 +1870,8 @@ pub const Parser = struct {
stack.append(State { .Block = inner_block }) catch unreachable;
continue;
},
+ Token.Id.Keyword_suspend, Token.Id.Keyword_if,
+ Token.Id.Keyword_while, Token.Id.Keyword_for,
Token.Id.Keyword_switch => {
self.putBackToken(next);
stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable;
@@ -2572,9 +2588,8 @@ pub const Parser = struct {
if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {
if (prefix_op_node.op.Catch) |payload| {
- try stack.append(RenderState { .Text = "| " });
- try stack.append(RenderState { .Expression = &payload.base });
- try stack.append(RenderState { .Text = "|" });
+ try stack.append(RenderState { .Text = " " });
+ try stack.append(RenderState { .Expression = payload });
}
try stack.append(RenderState { .Text = " catch " });
} else {
@@ -2764,6 +2779,17 @@ pub const Parser = struct {
try stack.append(RenderState { .Expression = rhs });
}
},
+ ast.Node.Id.Payload => {
+ const payload = @fieldParentPtr(ast.NodePayload, "base", base);
+ try stack.append(RenderState { .Text = "|"});
+ try stack.append(RenderState { .Expression = &payload.symbol.base });
+
+ if (payload.is_ptr) {
+ try stack.append(RenderState { .Text = "*"});
+ }
+
+ try stack.append(RenderState { .Text = "|"});
+ },
ast.Node.Id.GroupedExpression => {
const grouped_expr = @fieldParentPtr(ast.NodeGroupedExpression, "base", base);
try stack.append(RenderState { .Text = ")"});
@@ -2985,14 +3011,9 @@ pub const Parser = struct {
const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base);
try stack.append(RenderState { .Expression = switch_case.expr });
- if (switch_case.capture) |capture| {
- try stack.append(RenderState { .Text = "| "});
- try stack.append(RenderState { .Expression = &capture.symbol.base });
-
- if (capture.is_ptr) {
- try stack.append(RenderState { .Text = "*"});
- }
- try stack.append(RenderState { .Text = "|"});
+ if (switch_case.payload) |payload| {
+ try stack.append(RenderState { .Text = " " });
+ try stack.append(RenderState { .Expression = payload });
}
try stack.append(RenderState { .Text = " => "});
@@ -3011,6 +3032,7 @@ pub const Parser = struct {
const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base);
try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token));
},
+ ast.Node.Id.While => @panic("TODO: Render while"),
ast.Node.Id.StructField,
ast.Node.Id.UnionTag,