#include #include #include #include #include #include #include "calculator.h" FileIter fileiter(const char* filename) { return (FileIter) { .file = fopen(filename, "r"), .done = false, }; } char fileiter_next(FileIter* file) { if (file->done) return '\0'; int c = fgetc(file->file); if (c == EOF) { file->done = true; return '\0'; } else { return (char)c; } } Lexer lexer(FileIter input_file) { return (Lexer) { .input_file = input_file, .current = fileiter_next(&input_file), .pos = (Position) { .line = 1, .col = 1, }, }; } void lexer_step(Lexer* lexer) { lexer->current = fileiter_next(&lexer->input_file); if (lexer->current) { lexer->pos.line++; lexer->pos.col = 1; } else { lexer->pos.col++; } } Token lexer_single_token(Lexer* lexer, TokenType token_type) { Position pos = lexer->pos; lexer_step(lexer); return (Token) { .type = TokenTypePlus, .pos = pos, .value = NULL, }; } Token lexer_next(Lexer* lexer) { if (isspace(lexer->current)) { while (isspace(lexer->current)) lexer_step(lexer); return lexer_next(lexer); } else if (isdigit(lexer->current)) { Position pos = lexer->pos; size_t i = 0; char value[1234] = { 0 }; while (isdigit(lexer->current)) { value[i] = lexer->current; lexer_step(lexer); } char* allocated_value = malloc(sizeof(char) * strlen(value) + 1); strcpy(allocated_value, value); return (Token) { .type = TokenTypeInt, .pos = pos, .value = allocated_value, }; } else { switch (lexer->current) { case '+': return lexer_single_token(lexer, TokenTypePlus); case '-': return lexer_single_token(lexer, TokenTypeMinus); case '*': return lexer_single_token(lexer, TokenTypeAsterisk); case '/': return lexer_single_token(lexer, TokenTypeSlash); case '^': return lexer_single_token(lexer, TokenTypeHat); default: return lexer_single_token(lexer, TokenTypeInvalidChar); } } } Expr* allocate_expr(Expr data) { Expr* expr = malloc(sizeof(Expr)); *expr = data; return expr; } Parser parser(Lexer lexer) { return (Parser) { .lexer = lexer, .current = lexer_next(&lexer), }; } void parser_step(Parser* parser) { parser->current = lexer_next(&parser->lexer); } Expr* parser_parse_expr(Parser* parser) { return parser_parse_term(parser); } Expr* parser_parse_term(Parser* parser) { // Grammar // term -> factor (("+"|"-") factor):* Position pos = parser->current.pos; Expr* left = parser_parse_factor(parser); for (;;) { if (parser->current.type == TokenTypePlus) { parser_step(parser); Expr* right = parser_parse_factor(parser); left = allocate_expr((Expr) { .type = ExprTypeBinary, .pos = pos, .binary = (ExprBinary) { .type = ExprBinaryTypeAdd, .left = left, .right = right, }, }); } } } int main() { return EXIT_SUCCESS; }