/* E ::= UT{+T}{-T} T ::= F{*F}{/F} F ::= (E)|i U ::= -|+|_ '_' stands for empty sequence */ #include #include #include #include #define fatal(...) {\ fprintf(stderr, "\nError at char %d\n", number);\ fprintf(stderr, "%s\n", line);\ for (int i = 0; i < number - 1; i++)\ fputc(' ', stderr);\ fprintf(stderr, "^\nMessage: ");\ fprintf(stderr, __VA_ARGS__);\ exit(1);\ } typedef enum _NodeType { NNUM = 1, NOP = 2 } NodeType; typedef struct _Node Node; struct _Node { Node *parent; Node *left; Node *right; NodeType type; int number; char operator; // + - * / m p }; Node *e(); Node *t(); Node *f(); Node *u(); char line[1024]; int symbol; int number = 0; void scan(); int LRN(Node *node); int main(int argc, char* argv[]) { memset(line, 0, 1024); scan(); Node *root = e(); if (symbol != '\n') { fatal("Syntax invalid\n"); } printf("Success\n"); printf("Answer: %d\n", LRN(root)); return 0; } void scan() { symbol = getchar(); if (symbol == '\n') line[number++] = ' '; else line[number++] = symbol; } Node *e() { Node *left, *right, *root; root = u(); left = t(); if (root != NULL) { root->left = left; left = root; } while (symbol == '+' || symbol == '-') { root = calloc(sizeof(Node), 1); root->type = NOP; root->operator = symbol; scan(); right = t(); root->left = left; root->right = right; left->parent = root; right->parent = root; left = root; right = NULL; } return root; } Node *t() { Node *left, *right, *root; root = left = f(); while (symbol == '*' || symbol == '/') { root = calloc(sizeof(Node), 1); root->type = NOP; root->operator = symbol; scan(); right = f(); root->left = left; root->right = right; left->parent = root; right->parent = root; left = root; right = NULL; } return root; } Node *f() { Node *node; if (symbol == '(') { scan(); node = e(); if (symbol != ')') { fatal("Expected parentheses, found '%c'\n", symbol); } } else if (symbol < '0' || symbol > '9') { if (symbol == '\n') { fatal("LF too early\n"); } else { fatal("Unexpected symbol '%c'\n", symbol); } } else { node = calloc(sizeof(Node), 1); node->type = NNUM; node->number = (int) (symbol - '0'); } scan(); return node; } Node *u() { if (symbol == '-' || symbol == '+') { Node *node = calloc(sizeof(Node), 1); node->type = NOP; node->operator = (symbol == '+') ? 'p' : 'm'; scan(); return node; } return NULL; } int LRN(Node *node) { int l, r, answer; if (node == NULL) return 0; if (node->left != NULL) l = LRN(node->left); if (node->right != NULL) r = LRN(node->right); if (node->type == NOP) { switch (node->operator) { case '+': answer = l + r; break; case '-': answer = l - r; break; case '*': answer = l * r; break; case '/': answer = l / r; break; case 'm': answer = -l; break; case 'p': answer = +l; break; default: fatal("Invalid operator indentifier: '%c'\n", node->operator); break; } } else if (node->type == NNUM) { answer = node->number; } else { answer = 0; } free(node); return answer; }