aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff147
1 files changed, 145 insertions, 2 deletions
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;
}