#include #include #include #include #include #include "lexer.h" #include "tokenkind.h" // error handling void expectedError(const char *expectedStr) { fprintf(stderr, "%zu.%zu: error expected '%s' got '%s'\n", token.pos.line, token.pos.col, expectedStr, strTokenKind(token.kind)); exit(1); } void expected(enum TokenKind tokenKind) { if (tokenKind != token.kind) { expectedError(strTokenKind(tokenKind)); } } // for debugging void printWithIndent(size_t indent, const char *str) { #ifndef NDEBUG for (size_t i = 0; i < indent * 4; ++i) { printf(" "); } printf("%s\n", str); #endif // NDEBUG } // parse functions void parseInputSequence(size_t); void parseExprStatement(size_t); uint64_t parseExpr(size_t); uint64_t parseTerm(size_t); uint64_t parseFactor(size_t); void parseInputSequence(size_t indent) { while (token.kind != EOI) { parseExprStatement(indent + 1); } } void parseExprStatement(size_t indent) { printWithIndent(indent, "parseExprStatement"); printf("> %" PRIu64 "\n", parseExpr(indent + 1)); expected(SEMICOLON); getToken(); } uint64_t parseExpr(size_t indent) { printWithIndent(indent, "parseExpr"); uint64_t val = parseTerm(indent + 1); while (token.kind == PLUS || token.kind == MINUS) { printWithIndent(indent, strTokenKind(token.kind)); enum TokenKind op = token.kind; getToken(); uint64_t valRight = parseTerm(indent + 1); if (op == PLUS) { val += valRight; } else { val -= valRight; } } return val; } uint64_t parseTerm(size_t indent) { printWithIndent(indent, "parseTerm"); uint64_t val = parseFactor(indent + 1); while (token.kind == ASTERISK || token.kind == SLASH) { printWithIndent(indent, strTokenKind(token.kind)); enum TokenKind op = token.kind; getToken(); uint64_t valRight = parseFactor(indent + 1); if (op == ASTERISK) { val *= valRight; } else { val /= valRight; } } return val; } uint64_t parseFactor(size_t indent) { printWithIndent(indent, "parseFactor"); uint64_t val = 0; if (token.kind == DEC_LITERAL) { printWithIndent(indent, token.val.cstr); val = strtoull(token.val.cstr, 0, 10); getToken(); return val; } else if (token.kind == HEX_LITERAL) { printWithIndent(indent, token.val.cstr); val = strtoull(token.val.cstr, 0, 16); getToken(); return val; } else if (token.kind == OCT_LITERAL) { printWithIndent(indent, token.val.cstr); val = strtoull(token.val.cstr, 0, 8); getToken(); return val; } else if (token.kind == LPAREN) { printWithIndent(indent, strTokenKind(token.kind)); getToken(); val = parseExpr(indent + 1); expected(RPAREN); printWithIndent(indent, strTokenKind(token.kind)); getToken(); return val; } else { expectedError("factor"); return val; // never reached } } // test for the parse int main(void) { // we need a current token before we begin parsing getToken(); parseInputSequence(0); }