152 lines
2.5 KiB
C
152 lines
2.5 KiB
C
/*
|
|
|
|
E ::= T{+T}
|
|
T ::= F{*F}
|
|
F ::= (E)|i
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <ctype.h>
|
|
|
|
|
|
#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;
|
|
}
|