mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-14 09:52:23 -07:00
336 lines
4.0 KiB
Odin
336 lines
4.0 KiB
Odin
package odin_tokenizer
|
|
|
|
import "core:strings"
|
|
|
|
Token :: struct {
|
|
kind: Token_Kind,
|
|
text: string,
|
|
pos: Pos,
|
|
}
|
|
|
|
Pos :: struct {
|
|
file: string,
|
|
offset: int, // starting at 0
|
|
line: int, // starting at 1
|
|
column: int, // starting at 1
|
|
}
|
|
|
|
pos_compare :: proc(lhs, rhs: Pos) -> int {
|
|
if lhs.offset != rhs.offset {
|
|
return -1 if (lhs.offset < rhs.offset) else +1;
|
|
}
|
|
if lhs.line != rhs.line {
|
|
return -1 if (lhs.line < rhs.line) else +1;
|
|
}
|
|
if lhs.column != rhs.column {
|
|
return -1 if (lhs.column < rhs.column) else +1;
|
|
}
|
|
return strings.compare(lhs.file, rhs.file);
|
|
}
|
|
|
|
Token_Kind :: enum u32 {
|
|
Invalid,
|
|
EOF,
|
|
Comment,
|
|
|
|
B_Literal_Begin,
|
|
Ident,
|
|
Integer,
|
|
Float,
|
|
Imag,
|
|
Rune,
|
|
String,
|
|
B_Literal_End,
|
|
|
|
B_Operator_Begin,
|
|
Eq,
|
|
Not,
|
|
Hash,
|
|
At,
|
|
Dollar,
|
|
Pointer,
|
|
Question,
|
|
Add,
|
|
Sub,
|
|
Mul,
|
|
Quo,
|
|
Mod,
|
|
Mod_Mod,
|
|
And,
|
|
Or,
|
|
Xor,
|
|
And_Not,
|
|
Shl,
|
|
Shr,
|
|
|
|
Cmp_And,
|
|
Cmp_Or,
|
|
|
|
B_Assign_Op_Begin,
|
|
Add_Eq,
|
|
Sub_Eq,
|
|
Mul_Eq,
|
|
Quo_Eq,
|
|
Mod_Eq,
|
|
Mod_Mod_Eq,
|
|
And_Eq,
|
|
Or_Eq,
|
|
Xor_Eq,
|
|
And_Not_Eq,
|
|
Shl_Eq,
|
|
Shr_Eq,
|
|
Cmp_And_Eq,
|
|
Cmp_Or_Eq,
|
|
B_Assign_Op_End,
|
|
|
|
Arrow_Right,
|
|
Arrow_Left,
|
|
Double_Arrow_Right,
|
|
Undef,
|
|
|
|
B_Comparison_Begin,
|
|
Cmp_Eq,
|
|
Not_Eq,
|
|
Lt,
|
|
Gt,
|
|
Lt_Eq,
|
|
Gt_Eq,
|
|
B_Comparison_End,
|
|
|
|
Open_Paren,
|
|
Close_Paren,
|
|
Open_Bracket,
|
|
Close_Bracket,
|
|
Open_Brace,
|
|
Close_Brace,
|
|
Colon,
|
|
Semicolon,
|
|
Period,
|
|
Comma,
|
|
Ellipsis,
|
|
Range_Half,
|
|
Back_Slash,
|
|
B_Operator_End,
|
|
|
|
B_Keyword_Begin,
|
|
Import,
|
|
Foreign,
|
|
Package,
|
|
Typeid,
|
|
When,
|
|
Where,
|
|
If,
|
|
Else,
|
|
For,
|
|
Switch,
|
|
In,
|
|
Not_In,
|
|
Do,
|
|
Case,
|
|
Break,
|
|
Continue,
|
|
Fallthrough,
|
|
Defer,
|
|
Return,
|
|
Proc,
|
|
Macro,
|
|
Struct,
|
|
Union,
|
|
Enum,
|
|
Bit_Field,
|
|
Bit_Set,
|
|
Map,
|
|
Dynamic,
|
|
Auto_Cast,
|
|
Cast,
|
|
Transmute,
|
|
Distinct,
|
|
Opaque,
|
|
Using,
|
|
Inline,
|
|
No_Inline,
|
|
Context,
|
|
Size_Of,
|
|
Align_Of,
|
|
Offset_Of,
|
|
Type_Of,
|
|
Const,
|
|
B_Keyword_End,
|
|
|
|
COUNT,
|
|
|
|
B_Custom_Keyword_Begin = COUNT+1,
|
|
// ... Custom keywords
|
|
};
|
|
|
|
tokens := [Token_Kind.COUNT]string {
|
|
"Invalid",
|
|
"EOF",
|
|
"Comment",
|
|
|
|
"",
|
|
"identifier",
|
|
"integer",
|
|
"float",
|
|
"imaginary",
|
|
"rune",
|
|
"string",
|
|
"",
|
|
|
|
"",
|
|
"=",
|
|
"!",
|
|
"#",
|
|
"@",
|
|
"$",
|
|
"^",
|
|
"?",
|
|
"+",
|
|
"-",
|
|
"*",
|
|
"/",
|
|
"%",
|
|
"%%",
|
|
"&",
|
|
"|",
|
|
"~",
|
|
"&~",
|
|
"<<",
|
|
">>",
|
|
|
|
"&&",
|
|
"||",
|
|
|
|
"",
|
|
"+=",
|
|
"-=",
|
|
"*=",
|
|
"/=",
|
|
"%=",
|
|
"%%=",
|
|
"&=",
|
|
"|=",
|
|
"~=",
|
|
"&~=",
|
|
"<<=",
|
|
">>=",
|
|
"&&=",
|
|
"||=",
|
|
"",
|
|
|
|
"->",
|
|
"<-",
|
|
"=>",
|
|
"---",
|
|
|
|
"",
|
|
"==",
|
|
"!=",
|
|
"<",
|
|
">",
|
|
"<=",
|
|
">=",
|
|
"",
|
|
|
|
"(",
|
|
")",
|
|
"[",
|
|
"]",
|
|
"{",
|
|
"}",
|
|
":",
|
|
";",
|
|
".",
|
|
",",
|
|
"..",
|
|
"..<",
|
|
"\\",
|
|
"",
|
|
|
|
"",
|
|
"import",
|
|
"foreign",
|
|
"package",
|
|
"typeid",
|
|
"when",
|
|
"where",
|
|
"if",
|
|
"else",
|
|
"for",
|
|
"switch",
|
|
"in",
|
|
"not_in",
|
|
"do",
|
|
"case",
|
|
"break",
|
|
"continue",
|
|
"fallthrough",
|
|
"defer",
|
|
"return",
|
|
"proc",
|
|
"macro",
|
|
"struct",
|
|
"union",
|
|
"enum",
|
|
"bit_field",
|
|
"bit_set",
|
|
"map",
|
|
"dynamic",
|
|
"auto_cast",
|
|
"cast",
|
|
"transmute",
|
|
"distinct",
|
|
"opaque",
|
|
"using",
|
|
"inline",
|
|
"no_inline",
|
|
"context",
|
|
"size_of",
|
|
"align_of",
|
|
"offset_of",
|
|
"type_of",
|
|
"const",
|
|
"",
|
|
};
|
|
|
|
custom_keyword_tokens: []string;
|
|
|
|
to_string :: proc(kind: Token_Kind) -> string {
|
|
if Token_Kind.Invalid <= kind && kind < Token_Kind.COUNT {
|
|
return tokens[kind];
|
|
}
|
|
if Token_Kind.B_Custom_Keyword_Begin < kind {
|
|
n := int(u16(kind)-u16(Token_Kind.B_Custom_Keyword_Begin));
|
|
if n < len(custom_keyword_tokens) {
|
|
return custom_keyword_tokens[n];
|
|
}
|
|
}
|
|
|
|
return "Invalid";
|
|
}
|
|
|
|
is_literal :: proc(kind: Token_Kind) -> bool {
|
|
return Token_Kind.B_Literal_Begin < kind && kind < Token_Kind.B_Literal_End;
|
|
}
|
|
is_operator :: proc(kind: Token_Kind) -> bool {
|
|
#partial switch kind {
|
|
case .B_Operator_Begin .. .B_Operator_End:
|
|
return true;
|
|
case .In, .Not_In:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
is_assignment_operator :: proc(kind: Token_Kind) -> bool {
|
|
return Token_Kind.B_Assign_Op_Begin < kind && kind < Token_Kind.B_Assign_Op_End || kind == Token_Kind.Eq;
|
|
}
|
|
is_keyword :: proc(kind: Token_Kind) -> bool {
|
|
switch {
|
|
case Token_Kind.B_Keyword_Begin < kind && kind < Token_Kind.B_Keyword_End:
|
|
return true;
|
|
case Token_Kind.B_Custom_Keyword_Begin < kind:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|