From 19f1093f0929b989a06cdee2e7d175e6db15559c Mon Sep 17 00:00:00 2001 From: lemon Date: Thu, 11 Aug 2022 20:27:48 +0200 Subject: things --- src/parse.cff | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 2 deletions(-) (limited to 'src/parse.cff') diff --git a/src/parse.cff b/src/parse.cff index 089d647..f659322 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -1,5 +1,148 @@ import "all.hff"; -extern fn parse(P *Parser, path *const u8) [#]Decl { - return {}; +/////////// +// Lexer // +/////////// + +fn chr(P *Parser) int { + let c int #?; + switch P.peekchr { + case Some pc; + c = pc; + P.peekchr = :None; + case None; + c = fgetc(P.fp); + } + + ++P.curloc.idx; + ++P.curloc.col; + if c == '\n' { + P.curloc.col = 1; + ++P.curloc.line; + } + if c == EOF { + P.eof = #t; + } + return c; +} + +fn chrpeek(P *Parser) int { + switch P.peekchr { + case Some c; return c; + } + let c = fgetc(P.fp); + P.peekchr = :Some c; + return c; +} + +fn chrmatch(P *Parser, c int) bool { + if chrpeek(P) == c { + chr(P); + return #t; + } + return #f; +} + +fn isspace(c u8) bool { + switch c { + case ' ', '\t', '\n', '\r', '\v', '\f'; + return #t; + } + return #f; +} + +fn isdigit(c u8) bool { + return c >= '0' and c <= '9'; +} + +fn isxdigit(c u8) bool { + return isdigit(c) + or (c >= 'A' and c <= 'F') + or (c >= 'a' and c <= 'f'); +} + +fn isalpha(c u8) bool { + return (c >= 'a' and c <= 'z') + or (c >= 'A' and c <= 'z'); +} + +fn issep(c u8) bool { + if isspace(c) { + return #t; + } + switch (c) { + case '(', ')', '[', ']', '{', '}', '.', ',', + ';', '?', '+', '-', '*', '/', '&', '|', + '^', '~', '=', '\'', '"', '<', '>', ':', + '@', '#', '\\', '`'; + return #t; + } + return #f; +} + +fn eatspaces(P *Parser) void { + for ;;chr(P) { + if not isspace(chrpeek(P)) { + break; + } + } +} + +// !sorted +static keyword2str []*const u8 = { + "and", "as", "break", "case", "const", + "continue", "def", "defmacro", "do", + "else", "enum", "extern", "fn", + "for", "if", "import", "let", "not", + "or", "return", "sizeof", "static", + "struct", "switch", "typedef", "typeof", + "union", "while", +}; + +fn str2keyword(s *const u8) int { + let i = 0, j = keyword2str.#len - 1; + while i <= j { + let k = (j + i) / 2; + let cmp = strcmp(keyword2str[k], s); + if cmp == 0 { + return k; + } else if cmp < 0 { + i = k + 1; + } else { + j = k - 1; + } + } + return -1; +} + +fn lex(P *Parser) Tok { + let c int #?; + let tok Tok = {}; + + switch P.peektok { + case Some pt; + P.peektok = :None; + return pt; + } + + eatspaces(P); + tok.loc = (P.tokloc = P.curloc); + if isdigit(c = chrpeek(P)) { + let s [80]u8 = {}; + } +} + +extern fn parse(P *Parser) [#]Decl { + let tok = lex(P); +} + +extern fn parser_init(P *Parser, path *const u8) void { + *P = {}; + P.curfile = path; + if (P.fp = fopen(path, "r")) == #null { + perror(path); + exit(1); + } + P.tokloc = (P.curloc = { addfilepath(path), 0, 1, 1 }); + P.peekchr = :None; } -- cgit v1.2.3