214 lines
3.8 KiB
C
214 lines
3.8 KiB
C
/*
|
|
|
|
E ::= UT{+T}{-T}
|
|
T ::= F{*F}{/F}
|
|
F ::= (E)|i
|
|
U ::= -|+|_
|
|
|
|
'_' stands for empty sequence
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
|
|
#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;
|
|
}
|