token.odin 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package odin_token
  2. import "core:strings"
  3. Token :: struct {
  4. kind: Kind,
  5. text: string,
  6. pos: Pos,
  7. }
  8. Pos :: struct {
  9. file: string,
  10. offset: int, // starting at 0
  11. line: int, // starting at 1
  12. column: int, // starting at 1
  13. }
  14. pos_compare :: proc(lhs, rhs: Pos) -> int {
  15. if lhs.offset != rhs.offset {
  16. return (lhs.offset < rhs.offset) ? -1 : +1;
  17. }
  18. if lhs.line != rhs.line {
  19. return (lhs.line < rhs.line) ? -1 : +1;
  20. }
  21. if lhs.column != rhs.column {
  22. return (lhs.column < rhs.column) ? -1 : +1;
  23. }
  24. return strings.compare(lhs.file, rhs.file);
  25. }
  26. using Kind :: enum u32 {
  27. Invalid,
  28. EOF,
  29. Comment,
  30. B_Literal_Begin,
  31. Ident,
  32. Integer,
  33. Float,
  34. Imag,
  35. Rune,
  36. String,
  37. B_Literal_End,
  38. B_Operator_Begin,
  39. Eq,
  40. Not,
  41. Hash,
  42. At,
  43. Dollar,
  44. Pointer,
  45. Question,
  46. Add,
  47. Sub,
  48. Mul,
  49. Quo,
  50. Mod,
  51. Mod_Mod,
  52. And,
  53. Or,
  54. Xor,
  55. And_Not,
  56. Shl,
  57. Shr,
  58. Cmp_And,
  59. Cmp_Or,
  60. B_Assign_Op_Begin,
  61. Add_Eq,
  62. Sub_Eq,
  63. Mul_Eq,
  64. Quo_Eq,
  65. Mod_Eq,
  66. Mod_Mod_Eq,
  67. And_Eq,
  68. Or_Eq,
  69. Xor_Eq,
  70. And_Not_Eq,
  71. Shl_Eq,
  72. Shr_Eq,
  73. Cmp_And_Eq,
  74. Cmp_Or_Eq,
  75. B_Assign_Op_End,
  76. Arrow_Right,
  77. Arrow_Left,
  78. Double_Arrow_Right,
  79. Undef,
  80. B_Comparison_Begin,
  81. Cmp_Eq,
  82. Not_Eq,
  83. Lt,
  84. Gt,
  85. Lt_Eq,
  86. Gt_Eq,
  87. B_Comparison_End,
  88. Open_Paren,
  89. Close_Paren,
  90. Open_Bracket,
  91. Close_Bracket,
  92. Open_Brace,
  93. Close_Brace,
  94. Colon,
  95. Semicolon,
  96. Period,
  97. Comma,
  98. Ellipsis,
  99. Range_Half,
  100. Back_Slash,
  101. B_Operator_End,
  102. B_Keyword_Begin,
  103. Import,
  104. Foreign,
  105. Package,
  106. Typeid,
  107. When,
  108. If,
  109. Else,
  110. For,
  111. Switch,
  112. In,
  113. Notin,
  114. Do,
  115. Case,
  116. Break,
  117. Continue,
  118. Fallthrough,
  119. Defer,
  120. Return,
  121. Proc,
  122. Macro,
  123. Struct,
  124. Union,
  125. Enum,
  126. Bit_Field,
  127. Bit_Set,
  128. Map,
  129. Dynamic,
  130. Auto_Cast,
  131. Cast,
  132. Transmute,
  133. Distinct,
  134. Opaque,
  135. Using,
  136. Inline,
  137. No_Inline,
  138. Context,
  139. Size_Of,
  140. Align_Of,
  141. Offset_Of,
  142. Type_Of,
  143. Const,
  144. Asm,
  145. Yield,
  146. Await,
  147. B_Keyword_End,
  148. COUNT,
  149. B_Custom_Keyword_Begin = COUNT+1,
  150. // ... Custom keywords
  151. };
  152. tokens := [Kind.COUNT]string {
  153. "Invalid",
  154. "EOF",
  155. "Comment",
  156. "",
  157. "identifier",
  158. "integer",
  159. "float",
  160. "imaginary",
  161. "rune",
  162. "string",
  163. "",
  164. "",
  165. "=",
  166. "!",
  167. "#",
  168. "@",
  169. "$",
  170. "^",
  171. "?",
  172. "+",
  173. "-",
  174. "*",
  175. "/",
  176. "%",
  177. "%%",
  178. "&",
  179. "|",
  180. "~",
  181. "&~",
  182. "<<",
  183. ">>",
  184. "&&",
  185. "||",
  186. "",
  187. "+=",
  188. "-=",
  189. "*=",
  190. "/=",
  191. "%=",
  192. "%%=",
  193. "&=",
  194. "|=",
  195. "~=",
  196. "&~=",
  197. "<<=",
  198. ">>=",
  199. "&&=",
  200. "||=",
  201. "",
  202. "->",
  203. "<-",
  204. "=>",
  205. "---",
  206. "",
  207. "==",
  208. "!=",
  209. "<",
  210. ">",
  211. "<=",
  212. ">=",
  213. "",
  214. "(",
  215. ")",
  216. "[",
  217. "]",
  218. "{",
  219. "}",
  220. ":",
  221. ";",
  222. ".",
  223. ",",
  224. "..",
  225. "..<",
  226. "\\",
  227. "",
  228. "",
  229. "import",
  230. "foreign",
  231. "package",
  232. "typeid",
  233. "when",
  234. "if",
  235. "else",
  236. "for",
  237. "switch",
  238. "in",
  239. "notin",
  240. "do",
  241. "case",
  242. "break",
  243. "continue",
  244. "fallthrough",
  245. "defer",
  246. "return",
  247. "proc",
  248. "macro",
  249. "struct",
  250. "union",
  251. "enum",
  252. "bit_field",
  253. "bit_set",
  254. "map",
  255. "dynamic",
  256. "auto_cast",
  257. "cast",
  258. "transmute",
  259. "distinct",
  260. "opaque",
  261. "using",
  262. "inline",
  263. "no_inline",
  264. "context",
  265. "size_of",
  266. "align_of",
  267. "offset_of",
  268. "type_of",
  269. "const",
  270. "asm",
  271. "yield",
  272. "await",
  273. "",
  274. };
  275. custom_keyword_tokens: []string;
  276. to_string :: proc(kind: Kind) -> string {
  277. if Invalid <= kind && kind < COUNT {
  278. return tokens[kind];
  279. }
  280. if B_Custom_Keyword_Begin < kind {
  281. n := int(u16(kind)-u16(B_Custom_Keyword_Begin));
  282. if n < len(custom_keyword_tokens) {
  283. return custom_keyword_tokens[n];
  284. }
  285. }
  286. return "Invalid";
  287. }
  288. is_literal :: proc(kind: Kind) -> bool { return B_Literal_Begin < kind && kind < B_Literal_End; }
  289. is_operator :: proc(kind: Kind) -> bool {
  290. switch kind {
  291. case B_Operator_Begin..B_Operator_End:
  292. return true;
  293. case In, Notin:
  294. return true;
  295. }
  296. return false;
  297. }
  298. is_assignment_operator :: proc(kind: Kind) -> bool {
  299. return B_Assign_Op_Begin < kind && kind < B_Assign_Op_End || kind == Eq;
  300. }
  301. is_keyword :: proc(kind: Kind) -> bool {
  302. switch {
  303. case B_Keyword_Begin < kind && kind < B_Keyword_End:
  304. return true;
  305. case B_Custom_Keyword_Begin < kind:
  306. return true;
  307. }
  308. return false;
  309. }