From 0c8746ada674840980e28211b2e09c30cb811c88 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 25 Feb 2019 12:41:43 +0000 Subject: [PATCH 1/2] Add support for custom keywords in core:odin/* packages --- core/odin/parser/parser.odin | 6 +----- core/odin/token/token.odin | 28 +++++++++++++++++++++++----- core/odin/tokenizer/tokenizer.odin | 10 ++++++++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 4c43a20e5..c10a83e47 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -857,10 +857,6 @@ parse_foreign_block :: proc(p: ^Parser, tok: token.Token) -> ^ast.Foreign_Block_ foreign_library: ^ast.Expr; switch p.curr_tok.kind { - case token.Export: - i := ast.new(ast.Implicit, tok.pos, end_pos(tok)); - i.tok = expect_token(p, token.Export); - foreign_library = i; case token.Open_Brace: i := ast.new(ast.Ident, tok.pos, end_pos(tok)); i.name = "_"; @@ -903,7 +899,7 @@ parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl { tok := expect_token(p, token.Foreign); switch p.curr_tok.kind { - case token.Export, token.Ident, token.Open_Brace: + case token.Ident, token.Open_Brace: return parse_foreign_block(p, tok); case token.Import: diff --git a/core/odin/token/token.odin b/core/odin/token/token.odin index f52f6301e..7e985d46d 100644 --- a/core/odin/token/token.odin +++ b/core/odin/token/token.odin @@ -28,7 +28,7 @@ pos_compare :: proc(lhs, rhs: Pos) -> int { return strings.compare(lhs.file, rhs.file); } -using Kind :: enum u16 { +using Kind :: enum u32 { Invalid, EOF, Comment, @@ -113,7 +113,6 @@ using Kind :: enum u16 { B_Keyword_Begin, Import, - Export, Foreign, Package, Typeid, @@ -160,6 +159,9 @@ using Kind :: enum u16 { B_Keyword_End, COUNT, + + B_Custom_Keyword_Begin = COUNT+1, + // ... Custom keywords }; tokens := [Kind.COUNT]string { @@ -247,7 +249,6 @@ tokens := [Kind.COUNT]string { "", "import", - "export", "foreign", "package", "typeid", @@ -294,10 +295,19 @@ tokens := [Kind.COUNT]string { "", }; +custom_keyword_tokens: []string; + to_string :: proc(kind: Kind) -> string { - if min(Kind) <= kind && kind <= max(Kind) { + if Invalid <= kind && kind < COUNT { return tokens[kind]; } + if B_Custom_Keyword_Begin < kind { + n := int(u16(kind)-u16(B_Custom_Keyword_Begin)); + if n < len(custom_keyword_tokens) { + return custom_keyword_tokens[n]; + } + } + return "Invalid"; } @@ -314,4 +324,12 @@ is_operator :: proc(kind: Kind) -> bool { is_assignment_operator :: proc(kind: Kind) -> bool { return B_Assign_Op_Begin < kind && kind < B_Assign_Op_End || kind == Eq; } -is_keyword :: proc(kind: Kind) -> bool { return B_Keyword_Begin < kind && kind < B_Keyword_End; } +is_keyword :: proc(kind: Kind) -> bool { + switch { + case B_Keyword_Begin < kind && kind < B_Keyword_End: + return true; + case B_Custom_Keyword_Begin < kind: + return true; + } + return false; +} diff --git a/core/odin/tokenizer/tokenizer.odin b/core/odin/tokenizer/tokenizer.odin index a009d6ba3..fca475839 100644 --- a/core/odin/tokenizer/tokenizer.odin +++ b/core/odin/tokenizer/tokenizer.odin @@ -486,12 +486,18 @@ scan :: proc(t: ^Tokenizer) -> token.Token { case is_letter(ch): lit = scan_identifier(t); kind = token.Ident; - if len(lit) > 1 { + check_keyword: if len(lit) > 1 { // TODO(bill): Maybe have a hash table lookup rather than this linear search for i in token.B_Keyword_Begin .. token.B_Keyword_End { if lit == token.tokens[i] { kind = token.Kind(i); - break; + break check_keyword; + } + } + for keyword, i in token.custom_keyword_tokens { + if lit == keyword { + kind = token.Kind(i+1)+token.B_Custom_Keyword_Begin; + break check_keyword; } } } From 76a6757ee9e838326519ffb30a81dc60667d253d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 25 Feb 2019 18:03:44 +0000 Subject: [PATCH 2/2] Add `os.file_size_from_path` --- core/os/os.odin | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/os/os.odin b/core/os/os.odin index eda3b66cf..9db84ddfe 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -51,6 +51,20 @@ write_encoded_rune :: proc(fd: Handle, r: rune) { } +file_size_from_path :: proc(path: string) -> i64 { + fd, err := open(path, O_RDONLY, 0); + if err != 0 { + return -1; + } + defer close(fd); + + length: i64; + if length, err = file_size(fd); err != 0 { + return -1; + } + return length; +} + read_entire_file :: proc(name: string) -> (data: []byte, success: bool) { fd, err := open(name, O_RDONLY, 0); if err != 0 {