73 lines
1.9 KiB
C
73 lines
1.9 KiB
C
/* vim: set filetype=c: */
|
|
|
|
#include "lex.h"
|
|
#include "ast.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#define INPUT_SIZE 512
|
|
|
|
static void print_tokens(const Lex* lex) {
|
|
const TokenListItem* curr;
|
|
for(curr = lex->tokens.front; curr != NULL; curr = curr->next) {
|
|
Token_print(&curr->val, stdout);
|
|
fputc('\n', stdout);
|
|
}
|
|
}
|
|
|
|
static void handle_normal_err(const Result res, const char* domain) {
|
|
Result_print_err_or(res, domain, NULL, stderr, stdout);
|
|
if(res.has_err)
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int main() {
|
|
size_t i;
|
|
Result res;
|
|
char in[INPUT_SIZE];
|
|
|
|
Lex lex;
|
|
Lex_init(&lex);
|
|
|
|
printf("Enter an expression:\n");
|
|
for(i = 0;;i++) {
|
|
const char c = fgetc(stdin);
|
|
if(i >= INPUT_SIZE - 1 || c == '\n' || c == EOF) {
|
|
in[i] = '\0'; /* String terminator */
|
|
break;
|
|
}
|
|
in[i] = c;
|
|
}
|
|
for(i = 0; in[i] != '\0'; i++) {
|
|
res = Lex_lex_char(&lex, in[i]);
|
|
handle_normal_err(res, "Lexer error: ");
|
|
}
|
|
res = Lex_finish_lex(&lex);
|
|
handle_normal_err(res, "Lexer error: ");
|
|
printf("\n**Tokens**\n");
|
|
print_tokens(&lex);
|
|
res = Lex_apply_op_precedence(&lex, "^", true);
|
|
handle_normal_err(res, "Lexer error: ");
|
|
res = Lex_apply_op_precedence(&lex, "*/", false);
|
|
handle_normal_err(res, "Lexer error: ");
|
|
res = Lex_apply_op_precedence(&lex, "+-", false);
|
|
handle_normal_err(res, "Lexer error: ");
|
|
printf("\n**Tokens (with operator precedence)**\n");
|
|
print_tokens(&lex);
|
|
|
|
AST ast;
|
|
AST_init(&ast);
|
|
res = AST_parse_from_TokenList(&ast, &lex.tokens);
|
|
handle_normal_err(res, "Parser error: ");
|
|
printf("\n**AST**\n");
|
|
Token_print_as_tree(ast.root, stdout);
|
|
|
|
long double result = AST_evaluate(&ast);
|
|
printf("Result: %Lf\n", result);
|
|
|
|
AST_uninit(&ast);
|
|
Lex_uninit(&lex);
|
|
return EXIT_SUCCESS;
|
|
}
|