zig fmt supports simple line comments

master
Andrew Kelley 2018-02-14 23:39:20 -05:00
parent cc26148ba7
commit 5f5880979e
3 changed files with 95 additions and 24 deletions

View File

@ -6,6 +6,7 @@ const mem = std.mem;
pub const Node = struct { pub const Node = struct {
id: Id, id: Id,
comment: ?&NodeLineComment,
pub const Id = enum { pub const Id = enum {
Root, Root,
@ -20,6 +21,7 @@ pub const Node = struct {
FloatLiteral, FloatLiteral,
StringLiteral, StringLiteral,
BuiltinCall, BuiltinCall,
LineComment,
}; };
pub fn iterate(base: &Node, index: usize) ?&Node { pub fn iterate(base: &Node, index: usize) ?&Node {
@ -36,6 +38,7 @@ pub const Node = struct {
Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index), Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
}; };
} }
@ -53,6 +56,7 @@ pub const Node = struct {
Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(),
Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(), Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(), Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
}; };
} }
@ -70,6 +74,7 @@ pub const Node = struct {
Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(),
Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(), Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(), Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
}; };
} }
}; };
@ -454,3 +459,20 @@ pub const NodeStringLiteral = struct {
return self.token; return self.token;
} }
}; };
pub const NodeLineComment = struct {
base: Node,
lines: ArrayList(Token),
pub fn iterate(self: &NodeLineComment, index: usize) ?&Node {
return null;
}
pub fn firstToken(self: &NodeLineComment) Token {
return self.lines.at(0);
}
pub fn lastToken(self: &NodeLineComment) Token {
return self.lines.at(self.lines.len - 1);
}
};

View File

@ -18,6 +18,7 @@ pub const Parser = struct {
put_back_tokens: [2]Token, put_back_tokens: [2]Token,
put_back_count: usize, put_back_count: usize,
source_file_name: []const u8, source_file_name: []const u8,
pending_line_comment_node: ?&ast.NodeLineComment,
pub const Tree = struct { pub const Tree = struct {
root_node: &ast.NodeRoot, root_node: &ast.NodeRoot,
@ -43,6 +44,7 @@ pub const Parser = struct {
.put_back_count = 0, .put_back_count = 0,
.source_file_name = source_file_name, .source_file_name = source_file_name,
.utility_bytes = []align(utility_bytes_align) u8{}, .utility_bytes = []align(utility_bytes_align) u8{},
.pending_line_comment_node = null,
}; };
} }
@ -131,6 +133,33 @@ pub const Parser = struct {
// warn("\n"); // warn("\n");
//} //}
// look for line comments
while (true) {
const token = self.getNextToken();
if (token.id == Token.Id.LineComment) {
const node = blk: {
if (self.pending_line_comment_node) |comment_node| {
break :blk comment_node;
} else {
const comment_node = try arena.create(ast.NodeLineComment);
*comment_node = ast.NodeLineComment {
.base = ast.Node {
.id = ast.Node.Id.LineComment,
.comment = null,
},
.lines = ArrayList(Token).init(arena),
};
self.pending_line_comment_node = comment_node;
break :blk comment_node;
}
};
try node.lines.append(token);
continue;
}
self.putBackToken(token);
break;
}
// This gives us 1 free append that can't fail // This gives us 1 free append that can't fail
const state = stack.pop(); const state = stack.pop();
@ -329,7 +358,7 @@ pub const Parser = struct {
Token.Id.Builtin => { Token.Id.Builtin => {
const node = try arena.create(ast.NodeBuiltinCall); const node = try arena.create(ast.NodeBuiltinCall);
*node = ast.NodeBuiltinCall { *node = ast.NodeBuiltinCall {
.base = ast.Node {.id = ast.Node.Id.BuiltinCall}, .base = self.initNode(ast.Node.Id.BuiltinCall),
.builtin_token = token, .builtin_token = token,
.params = ArrayList(&ast.Node).init(arena), .params = ArrayList(&ast.Node).init(arena),
.rparen_token = undefined, .rparen_token = undefined,
@ -350,7 +379,7 @@ pub const Parser = struct {
Token.Id.StringLiteral => { Token.Id.StringLiteral => {
const node = try arena.create(ast.NodeStringLiteral); const node = try arena.create(ast.NodeStringLiteral);
*node = ast.NodeStringLiteral { *node = ast.NodeStringLiteral {
.base = ast.Node {.id = ast.Node.Id.StringLiteral}, .base = self.initNode(ast.Node.Id.StringLiteral),
.token = token, .token = token,
}; };
try stack.append(State { try stack.append(State {
@ -359,6 +388,7 @@ pub const Parser = struct {
try stack.append(State.AfterOperand); try stack.append(State.AfterOperand);
continue; continue;
}, },
else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)), else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),
} }
}, },
@ -660,11 +690,19 @@ pub const Parser = struct {
} }
} }
fn initNode(self: &Parser, id: ast.Node.Id) ast.Node {
if (self.pending_line_comment_node) |comment_node| {
self.pending_line_comment_node = null;
return ast.Node {.id = id, .comment = comment_node};
}
return ast.Node {.id = id, .comment = null };
}
fn createRoot(self: &Parser, arena: &mem.Allocator) !&ast.NodeRoot { fn createRoot(self: &Parser, arena: &mem.Allocator) !&ast.NodeRoot {
const node = try arena.create(ast.NodeRoot); const node = try arena.create(ast.NodeRoot);
*node = ast.NodeRoot { *node = ast.NodeRoot {
.base = ast.Node {.id = ast.Node.Id.Root}, .base = self.initNode(ast.Node.Id.Root),
.decls = ArrayList(&ast.Node).init(arena), .decls = ArrayList(&ast.Node).init(arena),
// initialized when we get the eof token // initialized when we get the eof token
.eof_token = undefined, .eof_token = undefined,
@ -678,7 +716,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeVarDecl); const node = try arena.create(ast.NodeVarDecl);
*node = ast.NodeVarDecl { *node = ast.NodeVarDecl {
.base = ast.Node {.id = ast.Node.Id.VarDecl}, .base = self.initNode(ast.Node.Id.VarDecl),
.visib_token = *visib_token, .visib_token = *visib_token,
.mut_token = *mut_token, .mut_token = *mut_token,
.comptime_token = *comptime_token, .comptime_token = *comptime_token,
@ -701,7 +739,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeFnProto); const node = try arena.create(ast.NodeFnProto);
*node = ast.NodeFnProto { *node = ast.NodeFnProto {
.base = ast.Node {.id = ast.Node.Id.FnProto}, .base = self.initNode(ast.Node.Id.FnProto),
.visib_token = *visib_token, .visib_token = *visib_token,
.name_token = null, .name_token = null,
.fn_token = *fn_token, .fn_token = *fn_token,
@ -722,7 +760,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeParamDecl); const node = try arena.create(ast.NodeParamDecl);
*node = ast.NodeParamDecl { *node = ast.NodeParamDecl {
.base = ast.Node {.id = ast.Node.Id.ParamDecl}, .base = self.initNode(ast.Node.Id.ParamDecl),
.comptime_token = null, .comptime_token = null,
.noalias_token = null, .noalias_token = null,
.name_token = null, .name_token = null,
@ -736,7 +774,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeBlock); const node = try arena.create(ast.NodeBlock);
*node = ast.NodeBlock { *node = ast.NodeBlock {
.base = ast.Node {.id = ast.Node.Id.Block}, .base = self.initNode(ast.Node.Id.Block),
.begin_token = *begin_token, .begin_token = *begin_token,
.end_token = undefined, .end_token = undefined,
.statements = ArrayList(&ast.Node).init(arena), .statements = ArrayList(&ast.Node).init(arena),
@ -748,7 +786,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeInfixOp); const node = try arena.create(ast.NodeInfixOp);
*node = ast.NodeInfixOp { *node = ast.NodeInfixOp {
.base = ast.Node {.id = ast.Node.Id.InfixOp}, .base = self.initNode(ast.Node.Id.InfixOp),
.op_token = *op_token, .op_token = *op_token,
.lhs = undefined, .lhs = undefined,
.op = *op, .op = *op,
@ -761,7 +799,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodePrefixOp); const node = try arena.create(ast.NodePrefixOp);
*node = ast.NodePrefixOp { *node = ast.NodePrefixOp {
.base = ast.Node {.id = ast.Node.Id.PrefixOp}, .base = self.initNode(ast.Node.Id.PrefixOp),
.op_token = *op_token, .op_token = *op_token,
.op = *op, .op = *op,
.rhs = undefined, .rhs = undefined,
@ -773,7 +811,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeIdentifier); const node = try arena.create(ast.NodeIdentifier);
*node = ast.NodeIdentifier { *node = ast.NodeIdentifier {
.base = ast.Node {.id = ast.Node.Id.Identifier}, .base = self.initNode(ast.Node.Id.Identifier),
.name_token = *name_token, .name_token = *name_token,
}; };
return node; return node;
@ -783,7 +821,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeIntegerLiteral); const node = try arena.create(ast.NodeIntegerLiteral);
*node = ast.NodeIntegerLiteral { *node = ast.NodeIntegerLiteral {
.base = ast.Node {.id = ast.Node.Id.IntegerLiteral}, .base = self.initNode(ast.Node.Id.IntegerLiteral),
.token = *token, .token = *token,
}; };
return node; return node;
@ -793,7 +831,7 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeFloatLiteral); const node = try arena.create(ast.NodeFloatLiteral);
*node = ast.NodeFloatLiteral { *node = ast.NodeFloatLiteral {
.base = ast.Node {.id = ast.Node.Id.FloatLiteral}, .base = self.initNode(ast.Node.Id.FloatLiteral),
.token = *token, .token = *token,
}; };
return node; return node;
@ -1158,9 +1196,11 @@ pub const Parser = struct {
} }
} }
}, },
ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
ast.Node.Id.Root, ast.Node.Id.Root,
ast.Node.Id.VarDecl, ast.Node.Id.VarDecl,
ast.Node.Id.FnProto,
ast.Node.Id.ParamDecl => unreachable, ast.Node.Id.ParamDecl => unreachable,
}, },
RenderState.FnProtoRParen => |fn_proto| { RenderState.FnProtoRParen => |fn_proto| {
@ -1187,6 +1227,12 @@ pub const Parser = struct {
} }
}, },
RenderState.Statement => |base| { RenderState.Statement => |base| {
if (base.comment) |comment| {
for (comment.lines.toSliceConst()) |line_token| {
try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token));
try stream.writeByteNTimes(' ', indent);
}
}
switch (base.id) { switch (base.id) {
ast.Node.Id.VarDecl => { ast.Node.Id.VarDecl => {
const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base); const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
@ -1279,6 +1325,17 @@ fn testCanonical(source: []const u8) !void {
} }
test "zig fmt" { test "zig fmt" {
try testCanonical(
\\const std = @import("std");
\\
\\pub fn main() !void {
\\ // If this program is run without stdout attached, exit with an error.
\\ // another comment
\\ var stdout_file = try std.io.getStdOut;
\\}
\\
);
try testCanonical( try testCanonical(
\\const std = @import("std"); \\const std = @import("std");
\\ \\

View File

@ -99,6 +99,7 @@ pub const Token = struct {
AmpersandEqual, AmpersandEqual,
IntegerLiteral, IntegerLiteral,
FloatLiteral, FloatLiteral,
LineComment,
Keyword_align, Keyword_align,
Keyword_and, Keyword_and,
Keyword_asm, Keyword_asm,
@ -470,7 +471,7 @@ pub const Tokenizer = struct {
State.Slash => switch (c) { State.Slash => switch (c) {
'/' => { '/' => {
result.id = undefined; result.id = Token.Id.LineComment;
state = State.LineComment; state = State.LineComment;
}, },
else => { else => {
@ -479,16 +480,7 @@ pub const Tokenizer = struct {
}, },
}, },
State.LineComment => switch (c) { State.LineComment => switch (c) {
'\n' => { '\n' => break,
state = State.Start;
result = Token {
.id = Token.Id.Eof,
.start = self.index + 1,
.column = 0,
.line = self.line + 1,
.end = undefined,
};
},
else => self.checkLiteralCharacter(), else => self.checkLiteralCharacter(),
}, },
State.Zero => switch (c) { State.Zero => switch (c) {