commit 652d7cd7f085580d451692526c646fcd2d658aa4 Author: Ilya Bezrukov Date: Tue Oct 15 20:35:50 2024 +0300 Initial diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d4e23c5 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +CC := gcc +CFLAGS := -Wall +LDFLAGS := +INCLUDE := -I include + +EXENAME := nrr + +OBJ := obj +BIN := bin + +SOURCES := main.c +OBJECTS := $(addprefix $(OBJ)/, $(SOURCES:.c=.o)) +TARGET := $(BIN)/$(EXENAME) + +all: $(TARGET) + +run: $(TARGET) + @./$(TARGET) + +$(TARGET): $(OBJECTS) | $(BIN) + $(CC) $(CFLAGS) $(INCLUDE) $(OBJECTS) -o $(TARGET) $(LDFLAGS) + +$(OBJ)/%.o: %.c | $(OBJ) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +$(BIN): + @mkdir -p $(BIN) + +$(OBJ): + @mkdir -p $(OBJ) + +clean: + @rm -rf $(BIN) $(OBJ) + +.PHONY: all clean run diff --git a/main.c b/main.c new file mode 100644 index 0000000..0655a91 --- /dev/null +++ b/main.c @@ -0,0 +1,213 @@ +/* + +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; +}