Initial
This commit is contained in:
commit
652d7cd7f0
35
Makefile
Normal file
35
Makefile
Normal file
@ -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
|
||||
213
main.c
Normal file
213
main.c
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
|
||||
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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user