std.zig.parser now parses for loops
parent
e24409ebe0
commit
7dd55a8007
150
std/zig/ast.zig
150
std/zig/ast.zig
|
@ -20,12 +20,15 @@ pub const Node = struct {
|
||||||
FnProto,
|
FnProto,
|
||||||
ParamDecl,
|
ParamDecl,
|
||||||
Block,
|
Block,
|
||||||
Payload,
|
ErrorPayload,
|
||||||
|
ValuePayload,
|
||||||
|
ValueIndexPayload,
|
||||||
Else,
|
Else,
|
||||||
Switch,
|
Switch,
|
||||||
SwitchCase,
|
SwitchCase,
|
||||||
SwitchElse,
|
SwitchElse,
|
||||||
While,
|
While,
|
||||||
|
For,
|
||||||
InfixOp,
|
InfixOp,
|
||||||
PrefixOp,
|
PrefixOp,
|
||||||
SuffixOp,
|
SuffixOp,
|
||||||
|
@ -61,12 +64,15 @@ pub const Node = struct {
|
||||||
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
|
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
|
||||||
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
|
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
|
||||||
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
|
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
|
||||||
Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index),
|
Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).iterate(index),
|
||||||
|
Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).iterate(index),
|
||||||
|
Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).iterate(index),
|
||||||
Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
|
Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
|
||||||
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
|
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
|
||||||
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
|
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
|
||||||
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
|
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
|
||||||
Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index),
|
Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index),
|
||||||
|
Id.For => @fieldParentPtr(NodeFor, "base", base).iterate(index),
|
||||||
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
|
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
|
||||||
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
|
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
|
||||||
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
|
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
|
||||||
|
@ -103,12 +109,15 @@ pub const Node = struct {
|
||||||
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
|
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
|
||||||
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
|
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
|
||||||
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
|
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
|
||||||
Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(),
|
Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).firstToken(),
|
||||||
|
Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).firstToken(),
|
||||||
|
Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).firstToken(),
|
||||||
Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
|
Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
|
||||||
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
|
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
|
||||||
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
|
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
|
||||||
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
|
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
|
||||||
Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(),
|
Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(),
|
||||||
|
Id.For => @fieldParentPtr(NodeFor, "base", base).firstToken(),
|
||||||
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
|
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
|
||||||
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
|
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
|
||||||
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
|
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
|
||||||
|
@ -145,12 +154,15 @@ pub const Node = struct {
|
||||||
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
|
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
|
||||||
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
|
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
|
||||||
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
|
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
|
||||||
Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(),
|
Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).lastToken(),
|
||||||
|
Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).lastToken(),
|
||||||
|
Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).lastToken(),
|
||||||
Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(),
|
Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(),
|
||||||
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
|
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
|
||||||
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
|
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
|
||||||
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
|
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
|
||||||
Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(),
|
Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(),
|
||||||
|
Id.For => @fieldParentPtr(NodeFor, "base", base).lastToken(),
|
||||||
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
|
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
|
||||||
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
|
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
|
||||||
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
|
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
|
||||||
|
@ -557,27 +569,82 @@ pub const NodeBlock = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const NodePayload = struct {
|
pub const NodeErrorPayload = struct {
|
||||||
base: Node,
|
base: Node,
|
||||||
lpipe: Token,
|
lpipe: Token,
|
||||||
is_ptr: bool,
|
error_symbol: &NodeIdentifier,
|
||||||
symbol: &NodeIdentifier,
|
|
||||||
rpipe: Token,
|
rpipe: Token,
|
||||||
|
|
||||||
pub fn iterate(self: &NodePayload, index: usize) ?&Node {
|
pub fn iterate(self: &NodeErrorPayload, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
if (i < 1) return &self.symbol.base;
|
if (i < 1) return &self.error_symbol.base;
|
||||||
i -= 1;
|
i -= 1;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn firstToken(self: &NodePayload) Token {
|
pub fn firstToken(self: &NodeErrorPayload) Token {
|
||||||
return self.lpipe;
|
return self.lpipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lastToken(self: &NodePayload) Token {
|
pub fn lastToken(self: &NodeErrorPayload) Token {
|
||||||
|
return self.rpipe;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const NodeValuePayload = struct {
|
||||||
|
base: Node,
|
||||||
|
lpipe: Token,
|
||||||
|
is_ptr: bool,
|
||||||
|
value_symbol: &NodeIdentifier,
|
||||||
|
rpipe: Token,
|
||||||
|
|
||||||
|
pub fn iterate(self: &NodeValuePayload, index: usize) ?&Node {
|
||||||
|
var i = index;
|
||||||
|
|
||||||
|
if (i < 1) return &self.value_symbol.base;
|
||||||
|
i -= 1;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn firstToken(self: &NodeValuePayload) Token {
|
||||||
|
return self.lpipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lastToken(self: &NodeValuePayload) Token {
|
||||||
|
return self.rpipe;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const NodeValueIndexPayload = struct {
|
||||||
|
base: Node,
|
||||||
|
lpipe: Token,
|
||||||
|
is_ptr: bool,
|
||||||
|
value_symbol: &NodeIdentifier,
|
||||||
|
index_symbol: ?&NodeIdentifier,
|
||||||
|
rpipe: Token,
|
||||||
|
|
||||||
|
pub fn iterate(self: &NodeValueIndexPayload, index: usize) ?&Node {
|
||||||
|
var i = index;
|
||||||
|
|
||||||
|
if (i < 1) return &self.value_symbol.base;
|
||||||
|
i -= 1;
|
||||||
|
|
||||||
|
if (self.index_symbol) |index_symbol| {
|
||||||
|
if (i < 1) return &index_symbol.base;
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn firstToken(self: &NodeValueIndexPayload) Token {
|
||||||
|
return self.lpipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lastToken(self: &NodeValueIndexPayload) Token {
|
||||||
return self.rpipe;
|
return self.rpipe;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -585,7 +652,7 @@ pub const NodePayload = struct {
|
||||||
pub const NodeElse = struct {
|
pub const NodeElse = struct {
|
||||||
base: Node,
|
base: Node,
|
||||||
else_token: Token,
|
else_token: Token,
|
||||||
payload: ?&NodePayload,
|
payload: ?&NodeErrorPayload,
|
||||||
body: &Node,
|
body: &Node,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeElse, index: usize) ?&Node {
|
pub fn iterate(self: &NodeElse, index: usize) ?&Node {
|
||||||
|
@ -642,7 +709,7 @@ pub const NodeSwitch = struct {
|
||||||
pub const NodeSwitchCase = struct {
|
pub const NodeSwitchCase = struct {
|
||||||
base: Node,
|
base: Node,
|
||||||
items: ArrayList(&Node),
|
items: ArrayList(&Node),
|
||||||
payload: ?&NodePayload,
|
payload: ?&NodeValuePayload,
|
||||||
expr: &Node,
|
expr: &Node,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
|
pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
|
||||||
|
@ -694,7 +761,7 @@ pub const NodeWhile = struct {
|
||||||
inline_token: ?Token,
|
inline_token: ?Token,
|
||||||
while_token: Token,
|
while_token: Token,
|
||||||
condition: &Node,
|
condition: &Node,
|
||||||
payload: ?&NodePayload,
|
payload: ?&NodeValuePayload,
|
||||||
continue_expr: ?&Node,
|
continue_expr: ?&Node,
|
||||||
body: &Node,
|
body: &Node,
|
||||||
@"else": ?&NodeElse,
|
@"else": ?&NodeElse,
|
||||||
|
@ -747,6 +814,59 @@ pub const NodeWhile = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const NodeFor = struct {
|
||||||
|
base: Node,
|
||||||
|
label: ?Token,
|
||||||
|
inline_token: ?Token,
|
||||||
|
for_token: Token,
|
||||||
|
array_expr: &Node,
|
||||||
|
payload: ?&NodeValueIndexPayload,
|
||||||
|
body: &Node,
|
||||||
|
@"else": ?&NodeElse,
|
||||||
|
|
||||||
|
pub fn iterate(self: &NodeFor, index: usize) ?&Node {
|
||||||
|
var i = index;
|
||||||
|
|
||||||
|
if (i < 1) return self.array_expr;
|
||||||
|
i -= 1;
|
||||||
|
|
||||||
|
if (self.payload) |payload| {
|
||||||
|
if (i < 1) return &payload.base;
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 1) return self.body;
|
||||||
|
i -= 1;
|
||||||
|
|
||||||
|
if (self.@"else") |@"else"| {
|
||||||
|
if (i < 1) return &@"else".base;
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn firstToken(self: &NodeFor) Token {
|
||||||
|
if (self.label) |label| {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.inline_token) |inline_token| {
|
||||||
|
return inline_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.for_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lastToken(self: &NodeFor) Token {
|
||||||
|
if (self.@"else") |@"else"| {
|
||||||
|
return @"else".body.lastToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.body.lastToken();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const NodeInfixOp = struct {
|
pub const NodeInfixOp = struct {
|
||||||
base: Node,
|
base: Node,
|
||||||
op_token: Token,
|
op_token: Token,
|
||||||
|
@ -781,7 +901,7 @@ pub const NodeInfixOp = struct {
|
||||||
BitXor,
|
BitXor,
|
||||||
BoolAnd,
|
BoolAnd,
|
||||||
BoolOr,
|
BoolOr,
|
||||||
Catch: ?&NodePayload,
|
Catch: ?&NodeErrorPayload,
|
||||||
Div,
|
Div,
|
||||||
EqualEqual,
|
EqualEqual,
|
||||||
ErrorUnion,
|
ErrorUnion,
|
||||||
|
|
|
@ -170,7 +170,9 @@ pub const Parser = struct {
|
||||||
FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
|
FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
|
||||||
FieldListCommaOrEnd: &ast.NodeContainerDecl,
|
FieldListCommaOrEnd: &ast.NodeContainerDecl,
|
||||||
SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
|
SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
|
||||||
Payload: &?&ast.NodePayload,
|
ErrorPayload: &?&ast.NodeErrorPayload,
|
||||||
|
ValuePayload: &?&ast.NodeValuePayload,
|
||||||
|
ValueIndexPayload: &?&ast.NodeValueIndexPayload,
|
||||||
SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
|
SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
|
||||||
SwitchCaseItem: &ArrayList(&ast.Node),
|
SwitchCaseItem: &ArrayList(&ast.Node),
|
||||||
SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
|
SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
|
||||||
|
@ -769,7 +771,7 @@ pub const Parser = struct {
|
||||||
|
|
||||||
stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
|
stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
|
||||||
try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
|
try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
|
||||||
try stack.append(State { .Payload = &node.op.Catch });
|
try stack.append(State { .ErrorPayload = &node.op.Catch });
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
Token.Id.QuestionMarkQuestionMark => {
|
Token.Id.QuestionMarkQuestionMark => {
|
||||||
|
@ -1471,7 +1473,15 @@ pub const Parser = struct {
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
Token.Id.Keyword_for => {
|
Token.Id.Keyword_for => {
|
||||||
@panic("TODO: inline for");
|
stack.append(State {
|
||||||
|
.For = LoopCtx {
|
||||||
|
.label = null,
|
||||||
|
.inline_token = null,
|
||||||
|
.loop_token = token,
|
||||||
|
.dest_ptr = dest_ptr,
|
||||||
|
}
|
||||||
|
}) catch unreachable;
|
||||||
|
continue;
|
||||||
},
|
},
|
||||||
Token.Id.Keyword_switch => {
|
Token.Id.Keyword_switch => {
|
||||||
const node = try arena.create(ast.NodeSwitch);
|
const node = try arena.create(ast.NodeSwitch);
|
||||||
|
@ -1614,7 +1624,7 @@ pub const Parser = struct {
|
||||||
try list_state.list.append(node);
|
try list_state.list.append(node);
|
||||||
stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
|
stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
|
||||||
try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
|
try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
|
||||||
try stack.append(State { .Payload = &node.payload });
|
try stack.append(State { .ValuePayload = &node.payload });
|
||||||
|
|
||||||
const maybe_else = self.getNextToken();
|
const maybe_else = self.getNextToken();
|
||||||
if (maybe_else.id == Token.Id.Keyword_else) {
|
if (maybe_else.id == Token.Id.Keyword_else) {
|
||||||
|
@ -1681,7 +1691,7 @@ pub const Parser = struct {
|
||||||
*dest = node;
|
*dest = node;
|
||||||
|
|
||||||
stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable;
|
stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable;
|
||||||
try stack.append(State { .Payload = &node.payload });
|
try stack.append(State { .ErrorPayload = &node.payload });
|
||||||
},
|
},
|
||||||
|
|
||||||
State.WhileContinueExpr => |dest| {
|
State.WhileContinueExpr => |dest| {
|
||||||
|
@ -1696,7 +1706,26 @@ pub const Parser = struct {
|
||||||
try stack.append(State { .Expression = DestPtr { .NullableField = dest } });
|
try stack.append(State { .Expression = DestPtr { .NullableField = dest } });
|
||||||
},
|
},
|
||||||
|
|
||||||
State.Payload => |dest| {
|
State.ErrorPayload => |dest| {
|
||||||
|
const lpipe = self.getNextToken();
|
||||||
|
if (lpipe.id != Token.Id.Pipe) {
|
||||||
|
self.putBackToken(lpipe);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const error_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||||
|
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
|
||||||
|
const node = try arena.create(ast.NodeErrorPayload);
|
||||||
|
*node = ast.NodeErrorPayload {
|
||||||
|
.base = self.initNode(ast.Node.Id.ErrorPayload),
|
||||||
|
.lpipe = lpipe,
|
||||||
|
.error_symbol = try self.createIdentifier(arena, error_symbol),
|
||||||
|
.rpipe = rpipe
|
||||||
|
};
|
||||||
|
*dest = node;
|
||||||
|
},
|
||||||
|
|
||||||
|
State.ValuePayload => |dest| {
|
||||||
const lpipe = self.getNextToken();
|
const lpipe = self.getNextToken();
|
||||||
if (lpipe.id != Token.Id.Pipe) {
|
if (lpipe.id != Token.Id.Pipe) {
|
||||||
self.putBackToken(lpipe);
|
self.putBackToken(lpipe);
|
||||||
|
@ -1713,14 +1742,56 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||||
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
|
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
|
||||||
const node = try arena.create(ast.NodePayload);
|
const node = try arena.create(ast.NodeValuePayload);
|
||||||
*node = ast.NodePayload {
|
*node = ast.NodeValuePayload {
|
||||||
.base = self.initNode(ast.Node.Id.Payload),
|
.base = self.initNode(ast.Node.Id.ValuePayload),
|
||||||
.lpipe = lpipe,
|
.lpipe = lpipe,
|
||||||
.is_ptr = is_ptr,
|
.is_ptr = is_ptr,
|
||||||
.symbol = try self.createIdentifier(arena, ident),
|
.value_symbol = try self.createIdentifier(arena, value_symbol),
|
||||||
|
.rpipe = rpipe
|
||||||
|
};
|
||||||
|
*dest = node;
|
||||||
|
},
|
||||||
|
|
||||||
|
State.ValueIndexPayload => |dest| {
|
||||||
|
const lpipe = self.getNextToken();
|
||||||
|
if (lpipe.id != Token.Id.Pipe) {
|
||||||
|
self.putBackToken(lpipe);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const is_ptr = blk: {
|
||||||
|
const asterik = self.getNextToken();
|
||||||
|
if (asterik.id == Token.Id.Asterisk) {
|
||||||
|
break :blk true;
|
||||||
|
} else {
|
||||||
|
self.putBackToken(asterik);
|
||||||
|
break :blk false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||||
|
const index_symbol = blk: {
|
||||||
|
const comma = self.getNextToken();
|
||||||
|
if (comma.id != Token.Id.Comma) {
|
||||||
|
self.putBackToken(comma);
|
||||||
|
break :blk null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||||
|
break :blk try self.createIdentifier(arena, symbol);
|
||||||
|
};
|
||||||
|
|
||||||
|
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
|
||||||
|
const node = try arena.create(ast.NodeValueIndexPayload);
|
||||||
|
*node = ast.NodeValueIndexPayload {
|
||||||
|
.base = self.initNode(ast.Node.Id.ValueIndexPayload),
|
||||||
|
.lpipe = lpipe,
|
||||||
|
.is_ptr = is_ptr,
|
||||||
|
.value_symbol = try self.createIdentifier(arena, value_symbol),
|
||||||
|
.index_symbol = index_symbol,
|
||||||
.rpipe = rpipe
|
.rpipe = rpipe
|
||||||
};
|
};
|
||||||
*dest = node;
|
*dest = node;
|
||||||
|
@ -1986,13 +2057,32 @@ pub const Parser = struct {
|
||||||
stack.append(State { .Else = &node.@"else" }) catch unreachable;
|
stack.append(State { .Else = &node.@"else" }) catch unreachable;
|
||||||
try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
|
try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
|
||||||
try stack.append(State { .WhileContinueExpr = &node.continue_expr });
|
try stack.append(State { .WhileContinueExpr = &node.continue_expr });
|
||||||
try stack.append(State { .Payload = &node.payload });
|
try stack.append(State { .ValuePayload = &node.payload });
|
||||||
try stack.append(State { .ExpectToken = Token.Id.RParen });
|
try stack.append(State { .ExpectToken = Token.Id.RParen });
|
||||||
try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });
|
try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });
|
||||||
try stack.append(State { .ExpectToken = Token.Id.LParen });
|
try stack.append(State { .ExpectToken = Token.Id.LParen });
|
||||||
},
|
},
|
||||||
|
|
||||||
State.For => |ctx| {
|
State.For => |ctx| {
|
||||||
|
const node = try arena.create(ast.NodeFor);
|
||||||
|
*node = ast.NodeFor {
|
||||||
|
.base = self.initNode(ast.Node.Id.For),
|
||||||
|
.label = ctx.label,
|
||||||
|
.inline_token = ctx.inline_token,
|
||||||
|
.for_token = ctx.loop_token,
|
||||||
|
.array_expr = undefined,
|
||||||
|
.payload = null,
|
||||||
|
.body = undefined,
|
||||||
|
.@"else" = null,
|
||||||
|
};
|
||||||
|
ctx.dest_ptr.store(&node.base);
|
||||||
|
|
||||||
|
stack.append(State { .Else = &node.@"else" }) catch unreachable;
|
||||||
|
try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
|
||||||
|
try stack.append(State { .ValueIndexPayload = &node.payload });
|
||||||
|
try stack.append(State { .ExpectToken = Token.Id.RParen });
|
||||||
|
try stack.append(State { .Expression = DestPtr { .Field = &node.array_expr } });
|
||||||
|
try stack.append(State { .ExpectToken = Token.Id.LParen });
|
||||||
},
|
},
|
||||||
|
|
||||||
State.Block => |block| {
|
State.Block => |block| {
|
||||||
|
@ -2071,7 +2161,9 @@ pub const Parser = struct {
|
||||||
ast.Node.Id.EnumTag,
|
ast.Node.Id.EnumTag,
|
||||||
ast.Node.Id.ParamDecl,
|
ast.Node.Id.ParamDecl,
|
||||||
ast.Node.Id.Block,
|
ast.Node.Id.Block,
|
||||||
ast.Node.Id.Payload,
|
ast.Node.Id.ErrorPayload,
|
||||||
|
ast.Node.Id.ValuePayload,
|
||||||
|
ast.Node.Id.ValueIndexPayload,
|
||||||
ast.Node.Id.Switch,
|
ast.Node.Id.Switch,
|
||||||
ast.Node.Id.SwitchCase,
|
ast.Node.Id.SwitchCase,
|
||||||
ast.Node.Id.SwitchElse,
|
ast.Node.Id.SwitchElse,
|
||||||
|
@ -2087,6 +2179,15 @@ pub const Parser = struct {
|
||||||
|
|
||||||
n = while_node.body;
|
n = while_node.body;
|
||||||
},
|
},
|
||||||
|
ast.Node.Id.For => {
|
||||||
|
const for_node = @fieldParentPtr(ast.NodeFor, "base", n);
|
||||||
|
if (for_node.@"else") |@"else"| {
|
||||||
|
n = @"else".base;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = for_node.body;
|
||||||
|
},
|
||||||
ast.Node.Id.Else => {
|
ast.Node.Id.Else => {
|
||||||
const else_node = @fieldParentPtr(ast.NodeElse, "base", n);
|
const else_node = @fieldParentPtr(ast.NodeElse, "base", n);
|
||||||
n = else_node.body;
|
n = else_node.body;
|
||||||
|
@ -2982,10 +3083,33 @@ pub const Parser = struct {
|
||||||
try stack.append(RenderState { .Expression = rhs });
|
try stack.append(RenderState { .Expression = rhs });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ast.Node.Id.Payload => {
|
ast.Node.Id.ErrorPayload => {
|
||||||
const payload = @fieldParentPtr(ast.NodePayload, "base", base);
|
const payload = @fieldParentPtr(ast.NodeErrorPayload, "base", base);
|
||||||
try stack.append(RenderState { .Text = "|"});
|
try stack.append(RenderState { .Text = "|"});
|
||||||
try stack.append(RenderState { .Expression = &payload.symbol.base });
|
try stack.append(RenderState { .Expression = &payload.error_symbol.base });
|
||||||
|
try stack.append(RenderState { .Text = "|"});
|
||||||
|
},
|
||||||
|
ast.Node.Id.ValuePayload => {
|
||||||
|
const payload = @fieldParentPtr(ast.NodeValuePayload, "base", base);
|
||||||
|
try stack.append(RenderState { .Text = "|"});
|
||||||
|
try stack.append(RenderState { .Expression = &payload.value_symbol.base });
|
||||||
|
|
||||||
|
if (payload.is_ptr) {
|
||||||
|
try stack.append(RenderState { .Text = "*"});
|
||||||
|
}
|
||||||
|
|
||||||
|
try stack.append(RenderState { .Text = "|"});
|
||||||
|
},
|
||||||
|
ast.Node.Id.ValueIndexPayload => {
|
||||||
|
const payload = @fieldParentPtr(ast.NodeValueIndexPayload, "base", base);
|
||||||
|
try stack.append(RenderState { .Text = "|"});
|
||||||
|
|
||||||
|
if (payload.index_symbol) |index_symbol| {
|
||||||
|
try stack.append(RenderState { .Expression = &index_symbol.base });
|
||||||
|
try stack.append(RenderState { .Text = ", "});
|
||||||
|
}
|
||||||
|
|
||||||
|
try stack.append(RenderState { .Expression = &payload.value_symbol.base });
|
||||||
|
|
||||||
if (payload.is_ptr) {
|
if (payload.is_ptr) {
|
||||||
try stack.append(RenderState { .Text = "*"});
|
try stack.append(RenderState { .Text = "*"});
|
||||||
|
@ -3303,6 +3427,48 @@ pub const Parser = struct {
|
||||||
try stack.append(RenderState { .Expression = while_node.condition });
|
try stack.append(RenderState { .Expression = while_node.condition });
|
||||||
try stack.append(RenderState { .Text = "(" });
|
try stack.append(RenderState { .Text = "(" });
|
||||||
},
|
},
|
||||||
|
ast.Node.Id.For => {
|
||||||
|
const for_node = @fieldParentPtr(ast.NodeFor, "base", base);
|
||||||
|
if (for_node.label) |label| {
|
||||||
|
try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (for_node.inline_token) |inline_token| {
|
||||||
|
try stream.print("{} ", self.tokenizer.getTokenSlice(inline_token));
|
||||||
|
}
|
||||||
|
|
||||||
|
try stream.print("{} ", self.tokenizer.getTokenSlice(for_node.for_token));
|
||||||
|
|
||||||
|
if (for_node.@"else") |@"else"| {
|
||||||
|
try stack.append(RenderState { .Expression = &@"else".base });
|
||||||
|
|
||||||
|
if (for_node.body.id == ast.Node.Id.Block) {
|
||||||
|
try stack.append(RenderState { .Text = " " });
|
||||||
|
} else {
|
||||||
|
try stack.append(RenderState { .Text = "\n" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (for_node.body.id == ast.Node.Id.Block) {
|
||||||
|
try stack.append(RenderState { .Expression = for_node.body });
|
||||||
|
try stack.append(RenderState { .Text = " " });
|
||||||
|
} else {
|
||||||
|
try stack.append(RenderState { .Indent = indent });
|
||||||
|
try stack.append(RenderState { .Expression = for_node.body });
|
||||||
|
try stack.append(RenderState.PrintIndent);
|
||||||
|
try stack.append(RenderState { .Indent = indent + indent_delta });
|
||||||
|
try stack.append(RenderState { .Text = "\n" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (for_node.payload) |payload| {
|
||||||
|
try stack.append(RenderState { .Expression = &payload.base });
|
||||||
|
try stack.append(RenderState { .Text = " " });
|
||||||
|
}
|
||||||
|
|
||||||
|
try stack.append(RenderState { .Text = ")" });
|
||||||
|
try stack.append(RenderState { .Expression = for_node.array_expr });
|
||||||
|
try stack.append(RenderState { .Text = "(" });
|
||||||
|
},
|
||||||
|
|
||||||
ast.Node.Id.StructField,
|
ast.Node.Id.StructField,
|
||||||
ast.Node.Id.UnionTag,
|
ast.Node.Id.UnionTag,
|
||||||
|
@ -4022,10 +4188,10 @@ test "zig fmt: for" {
|
||||||
\\ continue;
|
\\ continue;
|
||||||
\\
|
\\
|
||||||
\\ const res = for (a) |v, i| {
|
\\ const res = for (a) |v, i| {
|
||||||
\\ breal v;
|
\\ break v;
|
||||||
\\ } else {
|
\\ } else {
|
||||||
\\ unreachable;
|
\\ unreachable;
|
||||||
\\ }
|
\\ };
|
||||||
\\
|
\\
|
||||||
\\ var num: usize = 0;
|
\\ var num: usize = 0;
|
||||||
\\ inline for (a) |v, i| {
|
\\ inline for (a) |v, i| {
|
||||||
|
|
Loading…
Reference in New Issue