#include #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); double parseExpr(size_t); double parseTerm(size_t); double parsePowerExpr(size_t); double parseUnaryExpr(size_t); double parseFactor(size_t); void parseInputSequence(size_t indent) { while (token.kind != EOI) { parseExprStatement(indent + 1); } } void parseExprStatement(size_t indent) { printWithIndent(indent, "parseExprStatement"); printf("> %lf\n", parseExpr(indent + 1)); expected(SEMICOLON); getToken(); } double parseExpr(size_t indent) { printWithIndent(indent, "parseExpr"); double val = parseTerm(indent + 1); while (token.kind == PLUS || token.kind == MINUS) { printWithIndent(indent, strTokenKind(token.kind)); enum TokenKind op = token.kind; getToken(); double valRight = parseTerm(indent + 1); if (op == PLUS) { val += valRight; } else { val -= valRight; } } return val; } double parseTerm(size_t indent) { printWithIndent(indent, "parseTerm"); double val = parsePowerExpr(indent + 1); while (token.kind == ASTERISK || token.kind == SLASH) { printWithIndent(indent, strTokenKind(token.kind)); enum TokenKind op = token.kind; getToken(); double valRight = parsePowerExpr(indent + 1); if (op == ASTERISK) { val *= valRight; } else { val /= valRight; } } return val; } double parsePowerExpr(size_t indent) { printWithIndent(indent, "parsePowerExpr"); double val = parseUnaryExpr(indent + 1); while (token.kind == CARET) { getToken(); double valRight = parsePowerExpr(indent + 1); val = pow(val, valRight); } return val; } double parseUnaryExpr(size_t indent) { printWithIndent(indent, "parseUnaryExpr"); if (token.kind == PLUS || token.kind == MINUS) { enum TokenKind op = token.kind; getToken(); double val = parseUnaryExpr(indent + 1); if (op == MINUS) { val = -val; } return val; } return parseFactor(indent + 1); } double parseFactor(size_t indent) { printWithIndent(indent, "parseFactor"); double 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); }