std.zig.parser now parses initializers... Or, it would, if it worked
parent
0b9247fb63
commit
5c82ed2ea9
|
@ -532,7 +532,7 @@ pub const NodePrefixOp = struct {
|
|||
|
||||
pub const NodeFieldInitializer = struct {
|
||||
base: Node,
|
||||
dot_token: Token,
|
||||
period_token: Token,
|
||||
name_token: Token,
|
||||
expr: &Node,
|
||||
|
||||
|
@ -546,7 +546,7 @@ pub const NodeFieldInitializer = struct {
|
|||
}
|
||||
|
||||
pub fn firstToken(self: &NodeFieldInitializer) Token {
|
||||
return self.dot_token;
|
||||
return self.period_token;
|
||||
}
|
||||
|
||||
pub fn lastToken(self: &NodeFieldInitializer) Token {
|
||||
|
|
|
@ -75,13 +75,16 @@ pub const Parser = struct {
|
|||
const ExpectTokenSave = struct {
|
||||
id: Token.Id,
|
||||
ptr: &Token,
|
||||
|
||||
};
|
||||
|
||||
const ExprListState = struct {
|
||||
list: &ArrayList(&ast.Node),
|
||||
end: Token.Id,
|
||||
ptr: &Token,
|
||||
};
|
||||
fn ListState(comptime T: type) type {
|
||||
return struct {
|
||||
list: &ArrayList(T),
|
||||
end: Token.Id,
|
||||
ptr: &Token,
|
||||
};
|
||||
}
|
||||
|
||||
const State = union(enum) {
|
||||
TopLevel,
|
||||
|
@ -110,8 +113,10 @@ pub const Parser = struct {
|
|||
FnDef: &ast.NodeFnProto,
|
||||
Block: &ast.NodeBlock,
|
||||
Statement: &ast.NodeBlock,
|
||||
ExprListItemOrEnd: ExprListState,
|
||||
ExprListCommaOrEnd: ExprListState,
|
||||
ExprListItemOrEnd: ListState(&ast.Node),
|
||||
ExprListCommaOrEnd: ListState(&ast.Node),
|
||||
FieldInitListItemOrEnd: ListState(&ast.NodeFieldInitializer),
|
||||
FieldInitListCommaOrEnd: ListState(&ast.NodeFieldInitializer),
|
||||
};
|
||||
|
||||
/// Returns an AST tree, allocated with the parser's allocator.
|
||||
|
@ -536,7 +541,7 @@ pub const Parser = struct {
|
|||
});
|
||||
try stack.append(State.AfterOperand);
|
||||
try stack.append(State {
|
||||
.ExprListItemOrEnd = ExprListState {
|
||||
.ExprListItemOrEnd = ListState(&ast.Node) {
|
||||
.list = &node.params,
|
||||
.end = Token.Id.RParen,
|
||||
.ptr = &node.rparen_token,
|
||||
|
@ -647,8 +652,6 @@ pub const Parser = struct {
|
|||
continue;
|
||||
|
||||
} else if (token.id == Token.Id.LParen) {
|
||||
self.putBackToken(token);
|
||||
|
||||
const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
|
||||
.Call = ast.NodeSuffixOp.CallInfo {
|
||||
.params = ArrayList(&ast.Node).init(arena),
|
||||
|
@ -658,18 +661,12 @@ pub const Parser = struct {
|
|||
try stack.append(State { .SuffixOp = node });
|
||||
try stack.append(State.AfterOperand);
|
||||
try stack.append(State {
|
||||
.ExprListItemOrEnd = ExprListState {
|
||||
.ExprListItemOrEnd = ListState(&ast.Node) {
|
||||
.list = &node.op.Call.params,
|
||||
.end = Token.Id.RParen,
|
||||
.ptr = &node.rtoken,
|
||||
}
|
||||
});
|
||||
try stack.append(State {
|
||||
.ExpectTokenSave = ExpectTokenSave {
|
||||
.id = Token.Id.LParen,
|
||||
.ptr = &node.rtoken,
|
||||
},
|
||||
});
|
||||
continue;
|
||||
|
||||
} else if (token.id == Token.Id.LBracket) {
|
||||
|
@ -686,6 +683,47 @@ pub const Parser = struct {
|
|||
try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }});
|
||||
continue;
|
||||
|
||||
// TODO: This is the initializer parsing code. It doesn't work because of
|
||||
// the ambiguity between function bodies and initializers:
|
||||
// fn main() void {} or fn main() (void {})
|
||||
} else if (false) { //(token.id == Token.Id.LBrace) {
|
||||
const next = self.getNextToken();
|
||||
|
||||
switch (next.id) {
|
||||
Token.Id.Period => {
|
||||
self.putBackToken(token);
|
||||
|
||||
const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
|
||||
.StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena),
|
||||
});
|
||||
|
||||
try stack.append(State {
|
||||
.FieldInitListItemOrEnd = ListState(&ast.NodeFieldInitializer) {
|
||||
.list = &node.op.StructInitializer,
|
||||
.end = Token.Id.RBrace,
|
||||
.ptr = &node.rtoken,
|
||||
}
|
||||
});
|
||||
continue;
|
||||
},
|
||||
else => {
|
||||
self.putBackToken(token);
|
||||
|
||||
const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
|
||||
.ArrayInitializer = ArrayList(&ast.Node).init(arena),
|
||||
});
|
||||
|
||||
try stack.append(State {
|
||||
.ExprListItemOrEnd = ListState(&ast.Node) {
|
||||
.list = &node.op.ArrayInitializer,
|
||||
.end = Token.Id.RBrace,
|
||||
.ptr = &node.rtoken,
|
||||
}
|
||||
});
|
||||
continue;
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: Parse postfix operator
|
||||
} else {
|
||||
// no postfix/infix operator after this operand.
|
||||
|
@ -717,30 +755,89 @@ pub const Parser = struct {
|
|||
}
|
||||
},
|
||||
|
||||
State.ExprListItemOrEnd => |expr_list_state| {
|
||||
State.ExprListItemOrEnd => |list_state| {
|
||||
var token = self.getNextToken();
|
||||
|
||||
const IdTag = @TagType(Token.Id);
|
||||
if (IdTag(list_state.end) == token.id) {
|
||||
*list_state.ptr = token;
|
||||
continue;
|
||||
}
|
||||
|
||||
self.putBackToken(token);
|
||||
stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
|
||||
try stack.append(State { .Expression = DestPtr{.List = list_state.list} });
|
||||
},
|
||||
|
||||
State.ExprListCommaOrEnd => |list_state| {
|
||||
var token = self.getNextToken();
|
||||
switch (token.id) {
|
||||
Token.Id.RParen => continue,
|
||||
Token.Id.Comma => {
|
||||
stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable;
|
||||
},
|
||||
else => {
|
||||
self.putBackToken(token);
|
||||
stack.append(State { .ExprListCommaOrEnd = expr_list_state }) catch unreachable;
|
||||
try stack.append(State { .Expression = DestPtr{.List = expr_list_state.list} });
|
||||
const IdTag = @TagType(Token.Id);
|
||||
if (IdTag(list_state.end) == token.id) {
|
||||
*list_state.ptr = token;
|
||||
continue;
|
||||
}
|
||||
|
||||
return self.parseError(token, "expected ',' or {}, found {}", @tagName(list_state.end), @tagName(token.id));
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
State.ExprListCommaOrEnd => |expr_list_state| {
|
||||
State.FieldInitListItemOrEnd => |list_state| {
|
||||
var token = self.getNextToken();
|
||||
|
||||
const IdTag = @TagType(Token.Id);
|
||||
if (IdTag(list_state.end) == token.id){
|
||||
*list_state.ptr = token;
|
||||
continue;
|
||||
}
|
||||
|
||||
self.putBackToken(token);
|
||||
|
||||
const node = try arena.create(ast.NodeFieldInitializer);
|
||||
*node = ast.NodeFieldInitializer {
|
||||
.base = self.initNode(ast.Node.Id.FieldInitializer),
|
||||
.period_token = undefined,
|
||||
.name_token = undefined,
|
||||
.expr = undefined,
|
||||
};
|
||||
try list_state.list.append(node);
|
||||
|
||||
stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
|
||||
try stack.append(State { .Expression = DestPtr{.Field = &node.expr} });
|
||||
try stack.append(State { .ExpectToken = Token.Id.Equal });
|
||||
try stack.append(State {
|
||||
.ExpectTokenSave = ExpectTokenSave {
|
||||
.id = Token.Id.Identifier,
|
||||
.ptr = &node.name_token,
|
||||
}
|
||||
});
|
||||
try stack.append(State {
|
||||
.ExpectTokenSave = ExpectTokenSave {
|
||||
.id = Token.Id.Period,
|
||||
.ptr = &node.period_token,
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
State.FieldInitListCommaOrEnd => |list_state| {
|
||||
var token = self.getNextToken();
|
||||
switch (token.id) {
|
||||
Token.Id.Comma => {
|
||||
stack.append(State { .ExprListItemOrEnd = expr_list_state }) catch unreachable;
|
||||
stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable;
|
||||
},
|
||||
else => {
|
||||
const IdTag = @TagType(Token.Id);
|
||||
if (IdTag(expr_list_state.end) == token.id)
|
||||
if (IdTag(list_state.end) == token.id) {
|
||||
*list_state.ptr = token;
|
||||
continue;
|
||||
}
|
||||
|
||||
return self.parseError(token, "expected ',' or {}, found {}", @tagName(expr_list_state.end), @tagName(token.id));
|
||||
return self.parseError(token, "expected ',' or {}, found {}", @tagName(list_state.end), @tagName(token.id));
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue