#ifndef LEX_H #define LEX_H #include "str.h" #define LEX_TOK_LIST\ X(EOF, "end-of-file")\ X(IDENT, "identifier")\ X(PROC, "proc")\ X(LET, "let")\ X(VAR, "var")\ X(CONST, "const")\ X(RETURN, "return")\ X(TRUE, "true")\ X(FALSE, "false")\ X(LBRACE, "{")\ X(RBRACE, "}")\ X(LPAREN, "(")\ X(RPAREN, ")")\ X(PLUS, "+")\ X(MINUS, "-")\ X(ASTERISK, "*")\ X(SLASH, "/")\ X(COLON, ":")\ X(COMMA, ",")\ X(NOT, "~")\ X(AND, "&")\ X(OR, "|")\ X(XOR, "xor")\ X(SHL, "<<")\ X(SHR, ">>")\ X(ASSIGN, ":=")\ X(EQL, "=")\ X(NEQ, "<>")\ X(LES, "<")\ X(GTR, ">")\ X(LTE, "<=")\ X(GTE, ">=")\ X(LIT_STR, "string")\ X(LIT_CHAR, "character")\ X(LIT_NUM, "number") #define LEX_TOK_CHAR_LIST\ X(TOK_LBRACE, '{')\ X(TOK_RBRACE, '}')\ X(TOK_LPAREN, '(')\ X(TOK_RPAREN, ')')\ X(TOK_PLUS, '+')\ X(TOK_MINUS, '-')\ X(TOK_ASTERISK, '*')\ X(TOK_SLASH, '/')\ X(TOK_EQL, '=')\ X(TOK_COMMA, ',')\ X(TOK_NOT, '~')\ X(TOK_AND, '&')\ X(TOK_OR, '|') typedef enum { #define X(n, s) TOK_##n, LEX_TOK_LIST #undef X TOK_MAX, } Token; static const char *lex_tok_str[TOK_MAX] = { #define X(n, s) s, LEX_TOK_LIST #undef X }; #define TMASK(t) (1L << t) typedef enum { #define X(n, s) TM_##n = TMASK(TOK_##n), LEX_TOK_LIST #undef X } TokMask; typedef struct { int ofs, n; } LexSpan; typedef struct { Token tok; Str ident; LexSpan pos; Str filename, buf; Arena arena; int ofs; } Lexer; typedef enum { LE_NONE, LE_WARN, LE_ERROR } LexErr; void lex_start(Lexer *l, const char *path); void lex_free(Lexer *l); void lex_expected(Lexer *l, TokMask t); void lex_expected_not(Lexer *l, TokMask t); void lex_expect(Lexer *l, TokMask t); /* next -> expected */ void lex_expect_not(Lexer *l, TokMask t); /* next -> expected_not */ void lex_error_at(Lexer *l, LexSpan pos, LexErr e, Str msg); void lex_error(Lexer *l, LexErr e, Str msg); void lex_pos(Lexer *l, int ofs, int *line, int *col); void lex_next(Lexer *l); #endif