/* E ::= T{+T} T ::= F{*F} F ::= (E)|i */ #include #include #include #include #include #define eprintf(...) fprintf(stderr, __VA_ARGS__) #define fatal(...) { eprintf(__VA_ARGS__); putc('\n', stderr); exit(1); } #define ENUM(x) x, #define STR(x) #x, #define __TokenType(f) \ f(EMPTY) \ f(INTEGER) \ f(PLUS) \ f(MULT) \ f(LBRACE) \ f(RBRACE) \ f(LF) \ f(EF) \ typedef enum TokenType { __TokenType(ENUM) } TokenType; const char *TokenTypeStr[] = { __TokenType(STR) }; typedef struct _Token { TokenType type; int value; } Token; Token scan(); int e(); int t(); int f(); static Token current; int main(int argc, char* argv[]) { current = scan(); int result = e(); printf("Success, result: %d\n", result); return 0; } Token scan() { static char prev_s = 0; Token token = {0, 0}; char s; if (prev_s) { s = prev_s; prev_s = 0; } else { s = getchar(); } while (isblank(s)) s = getchar(); while (s >= '0' && s <= '9') { token.type = INTEGER; token.value = token.value * 10 + ((int) (s - '0')); s = getchar(); } if (token.type == INTEGER) { prev_s = s; return token; } switch (s) { case '+': token.type = PLUS; break; case '*': token.type = MULT; break; case '(': token.type = LBRACE; break; case ')': token.type = RBRACE; break; case '\n': case '\r': case '\f': token.type = LF; break; case EOF: token.type = EF; break; default: fatal("Unexpected symbol: '%c' (%X)", s, s); break; } return token; } int e() { int result = t(); while (current.type == PLUS) { current = scan(); result += t(); } return result; } int t() { int result = f(); while (current.type == MULT) { current = scan(); result *= f(); } return result; } int f() { int result = 0; if (current.type == LBRACE) { current = scan(); result = e(); if (current.type != RBRACE) { fatal("Expected closing parentheses"); } } else if (current.type == INTEGER) { result = current.value; } else if (current.type == LF) { fatal("Unexpected line feed"); } else if (current.type == EF) { fatal("Unexpected EOF"); } else { fatal("Unexpected token: %s (%d)", TokenTypeStr[current.type], current.type); } current = scan(); return result; }