diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-02-13 11:53:20 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-02-13 11:53:20 -0500 |
| commit | e7ab2bc5534a53c57c900618ec2411542dc50f69 (patch) | |
| tree | 42c572bf7414f59a98cd40a37e7d2f5d94955084 /std | |
| parent | 7903a758a44d1a253f17a4a2383f36b5fdad8545 (diff) | |
| parent | c721354b73508ec53bf72d8e7fb304147676625d (diff) | |
| download | zig-e7ab2bc5534a53c57c900618ec2411542dc50f69.tar.gz zig-e7ab2bc5534a53c57c900618ec2411542dc50f69.zip | |
Merge remote-tracking branch 'origin/master' into llvm6
Diffstat (limited to 'std')
| -rw-r--r-- | std/zig/ast.zig | 32 | ||||
| -rw-r--r-- | std/zig/parser.zig | 3 | ||||
| -rw-r--r-- | std/zig/tokenizer.zig | 133 |
3 files changed, 138 insertions, 30 deletions
diff --git a/std/zig/ast.zig b/std/zig/ast.zig index a966c0316e..60824b22b8 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -18,6 +18,7 @@ pub const Node = struct { PrefixOp, IntegerLiteral, FloatLiteral, + BuiltinCall, }; pub fn iterate(base: &Node, index: usize) ?&Node { @@ -32,21 +33,7 @@ pub const Node = struct { Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), - }; - } - - pub fn destroy(base: &Node, allocator: &mem.Allocator) void { - return switch (base.id) { - Id.Root => allocator.destroy(@fieldParentPtr(NodeRoot, "base", base)), - Id.VarDecl => allocator.destroy(@fieldParentPtr(NodeVarDecl, "base", base)), - Id.Identifier => allocator.destroy(@fieldParentPtr(NodeIdentifier, "base", base)), - Id.FnProto => allocator.destroy(@fieldParentPtr(NodeFnProto, "base", base)), - Id.ParamDecl => allocator.destroy(@fieldParentPtr(NodeParamDecl, "base", base)), - Id.Block => allocator.destroy(@fieldParentPtr(NodeBlock, "base", base)), - Id.InfixOp => allocator.destroy(@fieldParentPtr(NodeInfixOp, "base", base)), - Id.PrefixOp => allocator.destroy(@fieldParentPtr(NodePrefixOp, "base", base)), - Id.IntegerLiteral => allocator.destroy(@fieldParentPtr(NodeIntegerLiteral, "base", base)), - Id.FloatLiteral => allocator.destroy(@fieldParentPtr(NodeFloatLiteral, "base", base)), + Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), }; } }; @@ -269,3 +256,18 @@ pub const NodeFloatLiteral = struct { return null; } }; + +pub const NodeBuiltinCall = struct { + base: Node, + builtin_token: Token, + params: ArrayList(&Node), + + pub fn iterate(self: &NodeBuiltinCall, index: usize) ?&Node { + var i = index; + + if (i < self.params.len) return self.params.at(i); + i -= self.params.len; + + return null; + } +}; diff --git a/std/zig/parser.zig b/std/zig/parser.zig index 4dbca8501e..792cc2d834 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -95,7 +95,8 @@ pub const Parser = struct { }; /// Returns an AST tree, allocated with the parser's allocator. - /// Result should be freed with `freeAst` when done. + /// Result should be freed with tree.deinit() when there are + /// no more references to any AST nodes of the tree. pub fn parse(self: &Parser) !Tree { var stack = self.initUtilityArrayList(State); defer self.deinitUtilityArrayList(stack); diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig index 546356caa3..de1263ac55 100644 --- a/std/zig/tokenizer.zig +++ b/std/zig/tokenizer.zig @@ -68,9 +68,12 @@ pub const Token = struct { Invalid, Identifier, StringLiteral: StrLitKind, + StringIdentifier, Eof, Builtin, Bang, + Pipe, + PipeEqual, Equal, EqualEqual, BangEqual, @@ -192,6 +195,7 @@ pub const Tokenizer = struct { StringLiteralBackslash, Equal, Bang, + Pipe, Minus, Slash, LineComment, @@ -205,6 +209,7 @@ pub const Tokenizer = struct { Ampersand, Period, Period2, + SawAtSign, }; pub fn next(self: &Tokenizer) Token { @@ -238,8 +243,7 @@ pub const Tokenizer = struct { result.id = Token.Id.Identifier; }, '@' => { - state = State.Builtin; - result.id = Token.Id.Builtin; + state = State.SawAtSign; }, '=' => { state = State.Equal; @@ -247,6 +251,9 @@ pub const Tokenizer = struct { '!' => { state = State.Bang; }, + '|' => { + state = State.Pipe; + }, '(' => { result.id = Token.Id.LParen; self.index += 1; @@ -313,6 +320,20 @@ pub const Tokenizer = struct { break; }, }, + + State.SawAtSign => switch (c) { + '"' => { + result.id = Token.Id.StringIdentifier; + state = State.StringLiteral; + }, + else => { + // reinterpret as a builtin + self.index -= 1; + state = State.Builtin; + result.id = Token.Id.Builtin; + }, + }, + State.Ampersand => switch (c) { '=' => { result.id = Token.Id.AmpersandEqual; @@ -379,6 +400,18 @@ pub const Tokenizer = struct { }, }, + State.Pipe => switch (c) { + '=' => { + result.id = Token.Id.PipeEqual; + self.index += 1; + break; + }, + else => { + result.id = Token.Id.Pipe; + break; + }, + }, + State.Equal => switch (c) { '=' => { result.id = Token.Id.EqualEqual; @@ -510,9 +543,62 @@ pub const Tokenizer = struct { else => break, }, } - } - result.end = self.index; + } else if (self.index == self.buffer.len) { + switch (state) { + State.Start, + State.C, + State.IntegerLiteral, + State.IntegerLiteralWithRadix, + State.FloatFraction, + State.FloatExponentNumber, + State.StringLiteral, // find this error later + State.Builtin => {}, + + State.Identifier => { + if (Token.getKeyword(self.buffer[result.start..self.index])) |id| { + result.id = id; + } + }, + State.LineComment => { + result.id = Token.Id.Eof; + }, + + State.NumberDot, + State.FloatExponentUnsigned, + State.SawAtSign, + State.StringLiteralBackslash => { + result.id = Token.Id.Invalid; + }, + State.Equal => { + result.id = Token.Id.Equal; + }, + State.Bang => { + result.id = Token.Id.Bang; + }, + State.Minus => { + result.id = Token.Id.Minus; + }, + State.Slash => { + result.id = Token.Id.Slash; + }, + State.Zero => { + result.id = Token.Id.IntegerLiteral; + }, + State.Ampersand => { + result.id = Token.Id.Ampersand; + }, + State.Period => { + result.id = Token.Id.Period; + }, + State.Period2 => { + result.id = Token.Id.Ellipsis2; + }, + State.Pipe => { + result.id = Token.Id.Pipe; + }, + } + } if (result.id == Token.Id.Eof) { if (self.pending_invalid_token) |token| { self.pending_invalid_token = null; @@ -520,6 +606,7 @@ pub const Tokenizer = struct { } } + result.end = self.index; return result; } @@ -551,7 +638,7 @@ pub const Tokenizer = struct { } else { // check utf8-encoded character. const length = std.unicode.utf8ByteSequenceLength(c0) catch return 1; - if (self.index + length >= self.buffer.len) { + if (self.index + length > self.buffer.len) { return u3(self.buffer.len - self.index); } const bytes = self.buffer[self.index..self.index + length]; @@ -632,15 +719,32 @@ test "tokenizer - illegal unicode codepoints" { testTokenize("//\xe2\x80\xaa", []Token.Id{}); } +test "tokenizer - string identifier and builtin fns" { + testTokenize( + \\const @"if" = @import("std"); + , + []Token.Id{ + Token.Id.Keyword_const, + Token.Id.StringIdentifier, + Token.Id.Equal, + Token.Id.Builtin, + Token.Id.LParen, + Token.Id {.StringLiteral = Token.StrLitKind.Normal}, + Token.Id.RParen, + Token.Id.Semicolon, + } + ); +} + +test "tokenizer - pipe and then invalid" { + testTokenize("||=", []Token.Id{ + Token.Id.Pipe, + Token.Id.PipeEqual, + }); +} + fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { - // (test authors, just make this bigger if you need it) - var padded_source: [0x100]u8 = undefined; - std.mem.copy(u8, padded_source[0..source.len], source); - padded_source[source.len + 0] = '\n'; - padded_source[source.len + 1] = '\n'; - padded_source[source.len + 2] = '\n'; - - var tokenizer = Tokenizer.init(padded_source[0..source.len + 3]); + var tokenizer = Tokenizer.init(source); for (expected_tokens) |expected_token_id| { const token = tokenizer.next(); std.debug.assert(@TagType(Token.Id)(token.id) == @TagType(Token.Id)(expected_token_id)); @@ -651,5 +755,6 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { else => {}, } } - std.debug.assert(tokenizer.next().id == Token.Id.Eof); + const last_token = tokenizer.next(); + std.debug.assert(last_token.id == Token.Id.Eof); } |
