Expression compiler
Given a expression this compiler generates C code that solves the expression and also reports errors.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> struct stream { const char* p; }; #define ch(S) (*(S)->p) #define match(S) ((S)->p++) void parse_expression(struct stream* stream, char* r); void parse_value(struct stream* stream, char* left) { if (ch(stream) >= '0' && ch(stream) <= '9') { while (ch(stream) >= '0' && ch(stream) <= '9') { *left = ch(stream); left++; match(stream); } *left = 0; } else if (ch(stream) >= 'a' && ch(stream) <= 'z') { while (ch(stream) >= 'a' && ch(stream) <= 'z') { *left = ch(stream); left++; match(stream); } *left = 0; } else if (ch(stream) == '(') { match(stream); parse_expression(stream, left); match(stream); } else { //error } } void parse_expression(struct stream* stream, char* right) { char left[100]; if ((ch(stream) >= '0' && ch(stream) <= '9') || (ch(stream) >= 'a' && ch(stream) <= 'z') || ch(stream) == '(') { parse_value(stream, left); } else { parse_expression(stream, left); } char op = ch(stream); if (op == '*' || op == '/') { match(stream); parse_expression(stream, right); if (op == '*') { printf(" if((%s == -1) && (%s == INT_MIN)) /*overflow */ return 1;\n", left, right); printf(" if((%s == -1) && (%s == INT_MIN)) /*overflow */ return 1;\n", right, left); printf(" if(%s > INT_MAX / %s) /* overflow */ return 1;\n", left, right); printf(" if(%s < INT_MIN / %s) /* overflow */ return 1;\n", left, right); } else { printf(" if((%s == INT_MIN) && (%s == -1)) /* a / b would overflow */ return 1;\n", left, right); } printf(" r = %s %c %s;\n\n", left, op, right); strcpy(right, "r"); } else if (op == '+' || op == '-') { match(stream); parse_expression(stream, right); if (op == '+') { printf(" if ((%s > 0) && (%s > INT_MAX - %s)) return 1; /*overflow*/\n", right, left, right); printf(" if ((%s < 0) && (%s < INT_MIN - %s)) return 1; /*underflow*/\n", right, left, right); } else { printf(" if ((%s < 0) && (%s > INT_MAX + %s)) return 1;\n", right, left, right); printf(" if ((%s > 0) && (%s < INT_MAX + %s)) return 1;\n", right, left, right); } printf(" r = %s %c %s;\n\n", left, op, right); strcpy(right, "r"); } else { strcpy(right, left); } } void solve(const char* p) { struct stream s = {.p = p}; printf("\n"); printf("/*%s*/\n", p); printf("int solve(int* result)\n"); printf("{\n"); printf(" int r;\n"); char r[100]; parse_expression(&s, r); printf(" *result = r;\n"); printf(" return 0;\n"); printf("}\n"); printf("\n"); } int main() { for (;;) { char input[128] = {0}; printf("> "); gets(input); solve(input); } }
/*a+b*c*/ int solve(int* result) { int r; if((b == -1) && (c == INT_MIN)) /*overflow */ return 1; if((c == -1) && (b == INT_MIN)) /*overflow */ return 1; if(b > INT_MAX / c) /* overflow */ return 1; if(b < INT_MIN / c) /* overflow */ return 1; r = b * c; if ((r > 0) && (a > INT_MAX - r)) return 1; /*overflow*/ if ((r < 0) && (a < INT_MIN - r)) return 1; /*underflow*/ r = a + r; *result = r; return 0; }