parser skeleton

This commit is contained in:
Andrew Kelley 2017-12-05 00:20:23 -05:00
parent 3976981ab3
commit 08d531143f

View File

@ -5,60 +5,66 @@ const heap = @import("std").heap;
const warn = @import("std").debug.warn;
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
const ArrayList = @import("std").ArrayList;
const Token = struct {
id: Id,
start: usize,
end: usize,
const Keyword = enum {
@"align",
@"and",
@"asm",
@"break",
@"coldcc",
@"comptime",
@"const",
@"continue",
@"defer",
@"else",
@"enum",
@"error",
@"export",
@"extern",
@"false",
@"fn",
@"for",
@"goto",
@"if",
@"inline",
@"nakedcc",
@"noalias",
@"null",
@"or",
@"packed",
@"pub",
@"return",
@"stdcallcc",
@"struct",
@"switch",
@"test",
@"this",
@"true",
@"undefined",
@"union",
@"unreachable",
@"use",
@"var",
@"volatile",
@"while",
const KeywordId = struct {
bytes: []const u8,
id: Id,
};
fn getKeyword(bytes: []const u8) -> ?Keyword {
comptime var i = 0;
inline while (i < @memberCount(Keyword)) : (i += 1) {
if (mem.eql(u8, @memberName(Keyword, i), bytes)) {
return Keyword(i);
const keywords = []KeywordId {
KeywordId{.bytes="align", .id = Id {.Keyword_align = {}}},
KeywordId{.bytes="and", .id = Id {.Keyword_and = {}}},
KeywordId{.bytes="asm", .id = Id {.Keyword_asm = {}}},
KeywordId{.bytes="break", .id = Id {.Keyword_break = {}}},
KeywordId{.bytes="coldcc", .id = Id {.Keyword_coldcc = {}}},
KeywordId{.bytes="comptime", .id = Id {.Keyword_comptime = {}}},
KeywordId{.bytes="const", .id = Id {.Keyword_const = {}}},
KeywordId{.bytes="continue", .id = Id {.Keyword_continue = {}}},
KeywordId{.bytes="defer", .id = Id {.Keyword_defer = {}}},
KeywordId{.bytes="else", .id = Id {.Keyword_else = {}}},
KeywordId{.bytes="enum", .id = Id {.Keyword_enum = {}}},
KeywordId{.bytes="error", .id = Id {.Keyword_error = {}}},
KeywordId{.bytes="export", .id = Id {.Keyword_export = {}}},
KeywordId{.bytes="extern", .id = Id {.Keyword_extern = {}}},
KeywordId{.bytes="false", .id = Id {.Keyword_false = {}}},
KeywordId{.bytes="fn", .id = Id {.Keyword_fn = {}}},
KeywordId{.bytes="for", .id = Id {.Keyword_for = {}}},
KeywordId{.bytes="goto", .id = Id {.Keyword_goto = {}}},
KeywordId{.bytes="if", .id = Id {.Keyword_if = {}}},
KeywordId{.bytes="inline", .id = Id {.Keyword_inline = {}}},
KeywordId{.bytes="nakedcc", .id = Id {.Keyword_nakedcc = {}}},
KeywordId{.bytes="noalias", .id = Id {.Keyword_noalias = {}}},
KeywordId{.bytes="null", .id = Id {.Keyword_null = {}}},
KeywordId{.bytes="or", .id = Id {.Keyword_or = {}}},
KeywordId{.bytes="packed", .id = Id {.Keyword_packed = {}}},
KeywordId{.bytes="pub", .id = Id {.Keyword_pub = {}}},
KeywordId{.bytes="return", .id = Id {.Keyword_return = {}}},
KeywordId{.bytes="stdcallcc", .id = Id {.Keyword_stdcallcc = {}}},
KeywordId{.bytes="struct", .id = Id {.Keyword_struct = {}}},
KeywordId{.bytes="switch", .id = Id {.Keyword_switch = {}}},
KeywordId{.bytes="test", .id = Id {.Keyword_test = {}}},
KeywordId{.bytes="this", .id = Id {.Keyword_this = {}}},
KeywordId{.bytes="true", .id = Id {.Keyword_true = {}}},
KeywordId{.bytes="undefined", .id = Id {.Keyword_undefined = {}}},
KeywordId{.bytes="union", .id = Id {.Keyword_union = {}}},
KeywordId{.bytes="unreachable", .id = Id {.Keyword_unreachable = {}}},
KeywordId{.bytes="use", .id = Id {.Keyword_use = {}}},
KeywordId{.bytes="var", .id = Id {.Keyword_var = {}}},
KeywordId{.bytes="volatile", .id = Id {.Keyword_volatile = {}}},
KeywordId{.bytes="while", .id = Id {.Keyword_while = {}}},
};
fn getKeyword(bytes: []const u8) -> ?Id {
for (keywords) |kw| {
if (mem.eql(u8, kw.bytes, bytes)) {
return kw.id;
}
}
return null;
@ -69,7 +75,6 @@ const Token = struct {
const Id = union(enum) {
Invalid,
Identifier,
Keyword: Keyword,
StringLiteral: StrLitKind,
Eof,
Builtin,
@ -83,6 +88,46 @@ const Token = struct {
Period,
Minus,
Arrow,
Keyword_align,
Keyword_and,
Keyword_asm,
Keyword_break,
Keyword_coldcc,
Keyword_comptime,
Keyword_const,
Keyword_continue,
Keyword_defer,
Keyword_else,
Keyword_enum,
Keyword_error,
Keyword_export,
Keyword_extern,
Keyword_false,
Keyword_fn,
Keyword_for,
Keyword_goto,
Keyword_if,
Keyword_inline,
Keyword_nakedcc,
Keyword_noalias,
Keyword_null,
Keyword_or,
Keyword_packed,
Keyword_pub,
Keyword_return,
Keyword_stdcallcc,
Keyword_struct,
Keyword_switch,
Keyword_test,
Keyword_this,
Keyword_true,
Keyword_undefined,
Keyword_union,
Keyword_unreachable,
Keyword_use,
Keyword_var,
Keyword_volatile,
Keyword_while,
};
};
@ -193,8 +238,8 @@ const Tokenizer = struct {
State.Identifier => switch (c) {
'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
else => {
if (Token.getKeyword(self.buffer[result.start..self.index])) |keyword_id| {
result.id = Token.Id { .Keyword = keyword_id };
if (Token.getKeyword(self.buffer[result.start..self.index])) |id| {
result.id = id;
}
break;
},
@ -251,6 +296,73 @@ const Tokenizer = struct {
}
};
const AstNode = struct {
};
const Parser = struct {
tokenizer: &Tokenizer,
allocator: &mem.Allocator,
fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator) -> Parser {
return Parser {
.tokenizer = tokenizer,
.allocator = allocator,
};
}
const StackFrame = struct {
};
const State = enum {
TopLevel,
Expression,
};
fn parse(self: &Parser) -> %void {
var stack = ArrayList(StackFrame).init(self.allocator);
defer stack.deinit();
var state = State.TopLevel;
while (true) {
const token = self.tokenizer.next();
switch (state) {
State.TopLevel => switch (token.id) {
Token.Id.Keyword_pub => {
const next_token = self.tokenizer.next();
switch (next_token.id) {
Token.Id.Keyword_fn => {
const fn_name = self.tokenizer.next();
if (@TagType(Token.Id)(fn_name.id) != Token.Id.Identifier) {
@panic("parse error");
}
const lparen = self.tokenizer.next();
if (@TagType(Token.Id)(lparen.id) != Token.Id.LParen) {
@panic("parse error");
}
},
Token.Id.Keyword_const => @panic("TODO"),
Token.Id.Keyword_var => @panic("TODO"),
Token.Id.Keyword_use => @panic("TODO"),
else => @panic("parse error"),
}
},
Token.Id.Keyword_const => @panic("TODO"),
Token.Id.Keyword_var => @panic("TODO"),
Token.Id.Keyword_fn => @panic("TODO"),
Token.Id.Keyword_export => @panic("TODO"),
Token.Id.Keyword_use => @panic("TODO"),
Token.Id.Keyword_comptime => @panic("TODO"),
else => @panic("parse error"),
},
State.Expression => @panic("TODO"),
}
}
}
};
pub fn main() -> %void {
main2() %% |err| {
@ -271,12 +383,18 @@ pub fn main2() -> %void {
warn("{}", target_file_buf);
var tokenizer = Tokenizer.init(target_file_buf);
while (true) {
const token = tokenizer.next();
tokenizer.dump(token);
if (@TagType(Token.Id)(token.id) == Token.Id.Eof) {
break;
{
var tokenizer = Tokenizer.init(target_file_buf);
while (true) {
const token = tokenizer.next();
tokenizer.dump(token);
if (@TagType(Token.Id)(token.id) == Token.Id.Eof) {
break;
}
}
}
var tokenizer = Tokenizer.init(target_file_buf);
var parser = Parser.init(&tokenizer, allocator);
%return parser.parse();
}