authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-09 15:40:16+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-09 15:40:16+02:00
loga09bb408a20fcfc0575a9298b318803b07517b0a
tree8c230a640a96d08edf2c123a0b15ff5125dbc572
parentaa552633cc0bc66d46f61ea2105f7a4392df37be

std.zig.parser now parses asm expressions

* We cannot render asm expressions yet

2 files changed, 178 insertions(+), 1 deletions(-)

std/zig/ast.zig+41
......@@ -47,6 +47,7 @@ pub const Node = struct {
4747 NullLiteral,
4848 UndefinedLiteral,
4949 ThisLiteral,
50 Asm,
5051 Unreachable,
5152 ErrorType,
5253 BuiltinCall,
......@@ -94,6 +95,7 @@ pub const Node = struct {
9495 Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).iterate(index),
9596 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),
9697 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),
98 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).iterate(index),
9799 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
98100 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
99101 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
......@@ -143,6 +145,7 @@ pub const Node = struct {
143145 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(),
144146 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),
145147 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
148 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),
146149 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
147150 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
148151 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
......@@ -190,6 +193,7 @@ pub const Node = struct {
190193 Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).lastToken(),
191194 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),
192195 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),
196 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),
193197 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
194198 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
195199 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
......@@ -1512,6 +1516,43 @@ pub const NodeThisLiteral = struct {
15121516 }
15131517};
15141518
1519pub const NodeAsm = struct {
1520 base: Node,
1521 asm_token: Token,
1522 is_volatile: bool,
1523 template: Token,
1524 //tokens: ArrayList(AsmToken),
1525 outputs: ArrayList(AsmOutput),
1526 inputs: ArrayList(AsmInput),
1527 cloppers: ArrayList(&NodeStringLiteral),
1528 rparen: Token,
1529
1530 const AsmOutput = struct {
1531 symbolic_name: Token,
1532 constraint: Token,
1533 variable_name: ?Token,
1534 return_type: ?&Node,
1535 };
1536
1537 const AsmInput = struct {
1538 symbolic_name: Token,
1539 constraint: Token,
1540 expr: &Node,
1541 };
1542
1543 pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
1544 return null;
1545 }
1546
1547 pub fn firstToken(self: &NodeAsm) Token {
1548 return self.asm_token;
1549 }
1550
1551 pub fn lastToken(self: &NodeAsm) Token {
1552 return self.rparen;
1553 }
1554};
1555
15151556pub const NodeUnreachable = struct {
15161557 base: Node,
15171558 token: Token,
std/zig/parser.zig+137-1
......@@ -164,6 +164,9 @@ pub const Parser = struct {
164164 WhileContinueExpr: &?&ast.Node,
165165 Statement: &ast.NodeBlock,
166166 Semicolon: &const &const ast.Node,
167 AsmOutputItems: &ArrayList(ast.NodeAsm.AsmOutput),
168 AsmInputItems: &ArrayList(ast.NodeAsm.AsmInput),
169 AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),
167170 ExprListItemOrEnd: ExprListCtx,
168171 ExprListCommaOrEnd: ExprListCtx,
169172 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
......@@ -1488,7 +1491,44 @@ pub const Parser = struct {
14881491 continue;
14891492 },
14901493 Token.Id.Keyword_asm => {
1491 @panic("TODO: inline asm");
1494 const is_volatile = blk: {
1495 const volatile_token = self.getNextToken();
1496 if (volatile_token.id != Token.Id.Keyword_volatile) {
1497 self.putBackToken(volatile_token);
1498 break :blk false;
1499 }
1500 break :blk true;
1501 };
1502 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1503 const template = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
1504 // TODO parse template
1505
1506 const node = try arena.create(ast.NodeAsm);
1507 *node = ast.NodeAsm {
1508 .base = self.initNode(ast.Node.Id.Asm),
1509 .asm_token = token,
1510 .is_volatile = is_volatile,
1511 .template = template,
1512 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
1513 .outputs = ArrayList(ast.NodeAsm.AsmOutput).init(arena),
1514 .inputs = ArrayList(ast.NodeAsm.AsmInput).init(arena),
1515 .cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),
1516 .rparen = undefined,
1517 };
1518 dest_ptr.store(&node.base);
1519
1520 stack.append(State {
1521 .ExpectTokenSave = ExpectTokenSave {
1522 .id = Token.Id.RParen,
1523 .ptr = &node.rparen,
1524 }
1525 }) catch unreachable;
1526 try stack.append(State { .AsmClopperItems = &node.cloppers });
1527 try stack.append(State { .IfToken = Token.Id.Colon });
1528 try stack.append(State { .AsmInputItems = &node.inputs });
1529 try stack.append(State { .IfToken = Token.Id.Colon });
1530 try stack.append(State { .AsmOutputItems = &node.outputs });
1531 try stack.append(State { .IfToken = Token.Id.Colon });
14921532 },
14931533 Token.Id.Keyword_if => {
14941534 const node = try arena.create(ast.NodeIf);
......@@ -1621,6 +1661,84 @@ pub const Parser = struct {
16211661 }
16221662 },
16231663
1664
1665 State.AsmOutputItems => |items| {
1666 const lbracket = self.getNextToken();
1667 if (lbracket.id != Token.Id.LBracket) {
1668 self.putBackToken(lbracket);
1669 continue;
1670 }
1671
1672 stack.append(State { .AsmOutputItems = items }) catch unreachable;
1673 try stack.append(State { .IfToken = Token.Id.Comma });
1674
1675 const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
1676 _ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue;
1677 const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
1678
1679 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1680 try stack.append(State { .ExpectToken = Token.Id.RParen });
1681
1682 const res = try items.addOne();
1683 *res = ast.NodeAsm.AsmOutput {
1684 .symbolic_name = symbolic_name,
1685 .constraint = constraint,
1686 .variable_name = null,
1687 .return_type = null,
1688 };
1689 const symbol_or_arrow = self.getNextToken();
1690 switch (symbol_or_arrow.id) {
1691 Token.Id.Identifier => res.variable_name = symbol_or_arrow,
1692 Token.Id.Arrow => {
1693 try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &res.return_type } });
1694 },
1695 else => {
1696 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
1697 @tagName(Token.Id.Identifier),
1698 @tagName(symbol_or_arrow.id));
1699 continue;
1700 },
1701 }
1702 },
1703
1704 State.AsmInputItems => |items| {
1705 const lbracket = self.getNextToken();
1706 if (lbracket.id != Token.Id.LBracket) {
1707 self.putBackToken(lbracket);
1708 continue;
1709 }
1710
1711 stack.append(State { .AsmInputItems = items }) catch unreachable;
1712 try stack.append(State { .IfToken = Token.Id.Comma });
1713
1714 const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
1715 _ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue;
1716 const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
1717
1718 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1719 try stack.append(State { .ExpectToken = Token.Id.RParen });
1720
1721 const res = try items.addOne();
1722 *res = ast.NodeAsm.AsmInput {
1723 .symbolic_name = symbolic_name,
1724 .constraint = constraint,
1725 .expr = undefined,
1726 };
1727 try stack.append(State { .Expression = DestPtr { .Field = &res.expr } });
1728 },
1729
1730 State.AsmClopperItems => |items| {
1731 const string = self.getNextToken();
1732 if (string.id != Token.Id.StringLiteral) {
1733 self.putBackToken(string);
1734 continue;
1735 }
1736
1737 try items.append(try self.createStringLiteral(arena, string));
1738 stack.append(State { .AsmClopperItems = items }) catch unreachable;
1739 try stack.append(State { .IfToken = Token.Id.Comma });
1740 },
1741
16241742 State.ExprListItemOrEnd => |list_state| {
16251743 var token = self.getNextToken();
16261744
......@@ -3675,6 +3793,24 @@ pub const Parser = struct {
36753793 try stack.append(RenderState { .Expression = if_node.condition });
36763794 try stack.append(RenderState { .Text = "(" });
36773795 },
3796 ast.Node.Id.Asm => {
3797 const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);
3798 try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));
3799
3800 if (asm_node.is_volatile) {
3801 try stream.write("volatile ");
3802 }
3803
3804 try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));
3805
3806 try stack.append(RenderState { .Text = ")" });
3807 @panic("TODO: Render asm");
3808 //\\ return asm volatile ("syscall"
3809 //\\ : [ret] "={rax}" (-> usize)
3810 //\\ : [number] "{rax}" (number),
3811 //\\ [arg1] "{rdi}" (arg1)
3812 //\\ : "rcx", "r11");
3813 },,
36783814
36793815 ast.Node.Id.StructField,
36803816 ast.Node.Id.UnionTag,