aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-02-13 11:53:20 -0500
committerAndrew Kelley <superjoe30@gmail.com>2018-02-13 11:53:20 -0500
commite7ab2bc5534a53c57c900618ec2411542dc50f69 (patch)
tree42c572bf7414f59a98cd40a37e7d2f5d94955084 /std
parent7903a758a44d1a253f17a4a2383f36b5fdad8545 (diff)
parentc721354b73508ec53bf72d8e7fb304147676625d (diff)
downloadzig-e7ab2bc5534a53c57c900618ec2411542dc50f69.tar.gz
zig-e7ab2bc5534a53c57c900618ec2411542dc50f69.zip
Merge remote-tracking branch 'origin/master' into llvm6
Diffstat (limited to 'std')
-rw-r--r--std/zig/ast.zig32
-rw-r--r--std/zig/parser.zig3
-rw-r--r--std/zig/tokenizer.zig133
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);
}