#include #include #include #include #include #include #include "expr.h" #include "finalize.h" #include "lexer.h" #include "parser.h" #include "sym.h" #include "tokenkind.h" // for log support static FILE *out; void setParserLog(FILE *out_) { out = out_; } // 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)); finalizeExit(1); } void errorAtPos(struct TokenPos pos, const char *msg) { fprintf(stderr, "%zu.%zu: %s\n", pos.line, pos.col, msg); finalizeExit(1); } void expected(enum TokenKind tokenKind) { if (tokenKind != token.kind) { expectedError(strTokenKind(tokenKind)); } } // parse functions void parseExprStatement(void); const struct Expr *parseAssignmentExpr(void); const struct Expr *parseExpr(void); const struct Expr *parseTerm(void); const struct Expr *parsePowerExpr(void); const struct Expr *parseUnaryExpr(void); const struct Expr *parseFactor(void); void parse(void) { while (token.kind != EOI) { parseExprStatement(); } } void parseExprStatement(void) { const struct Expr *expr = parseAssignmentExpr(); printf("> %lf\n", evalExpr(expr)); if (out) { printExprTree(expr, out); } deleteExpr(expr); expected(SEMICOLON); getToken(); } const struct Expr * parseAssignmentExpr(void) { struct TokenPos pos = token.pos; const struct Expr *expr = parseExpr(); while (token.kind == EQUAL) { if (!isLValueExpr(expr)) { // instead of many error functions we need a one error handling // function that is more flexible to use -> CBE about ellipse errorAtPos(pos, "L-value expected"); } getToken(); const struct Expr *exprRight = parseAssignmentExpr(); expr = newBinaryExpr(EK_ASSIGN, expr, exprRight); } return expr; } const struct Expr * parseExpr(void) { const struct Expr *expr = parseTerm(); while (token.kind == PLUS || token.kind == MINUS) { enum TokenKind op = token.kind; getToken(); const struct Expr *exprRight = parseTerm(); if (op == PLUS) { expr = newBinaryExpr(EK_ADD, expr, exprRight); } else { expr = newBinaryExpr(EK_SUB, expr, exprRight); } } return expr; } const struct Expr * parseTerm(void) { const struct Expr *expr = parsePowerExpr(); while (token.kind == ASTERISK || token.kind == SLASH) { enum TokenKind op = token.kind; getToken(); const struct Expr *exprRight = parsePowerExpr(); if (op == ASTERISK) { expr = newBinaryExpr(EK_MUL, expr, exprRight); } else { expr = newBinaryExpr(EK_DIV, expr, exprRight); } } return expr; } const struct Expr * parsePowerExpr(void) { const struct Expr *expr = parseUnaryExpr(); while (token.kind == CARET) { getToken(); const struct Expr *exprRight = parsePowerExpr(); expr = newBinaryExpr(EK_POW, expr, exprRight); } return expr; } const struct Expr * parseUnaryExpr(void) { if (token.kind == PLUS || token.kind == MINUS) { enum TokenKind op = token.kind; getToken(); const struct Expr *expr = parseUnaryExpr(); if (op == MINUS) { return newUnaryExpr(EK_UNARY_MINUS, expr); } return newUnaryExpr(EK_UNARY_PLUS, expr); } return parseFactor(); } const struct Expr * parseFactor(void) { if (token.kind == IDENTIFIER) { const struct UStr *identifier = UStrAdd(token.val.cstr); struct Sym *sym = SymFind(identifier); if (!sym) { SymAdd(identifier); } getToken(); return newIdentifierExpr(identifier); } else if (token.kind == DEC_LITERAL) { uint64_t uint = strtoull(token.val.cstr, 0, 10); getToken(); return newUnsignedLiteralExpr(uint); } else if (token.kind == HEX_LITERAL) { uint64_t uint = strtoull(token.val.cstr, 0, 10); getToken(); return newUnsignedLiteralExpr(uint); } else if (token.kind == OCT_LITERAL) { uint64_t uint = strtoull(token.val.cstr, 0, 10); getToken(); return newUnsignedLiteralExpr(uint); } else if (token.kind == LPAREN) { getToken(); const struct Expr *expr = parseAssignmentExpr(); expected(RPAREN); getToken(); return expr; } else { expectedError("factor"); return 0; // never reached } }