#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <string.h>
typedef enum TokenType_ {
TOKEN_TYPE_EOF,
TOKEN_TYPE_DELIM,
TOKEN_TYPE_NUM,
TOKEN_TYPE_X,
TOKEN_TYPE_PLUS,
TOKEN_TYPE_MINUS,
TOKEN_TYPE_EQUAL,
} TokenType;
/*
static const char* TOKEN_TYPE_STR[6] = {
"TOKEN_TYPE_EOF",
"TOKEN_TYPE_DELIM",
"TOKEN_TYPE_NUM",
"TOKEN_TYPE_X"
"TOKEN_TYPE_PLUS",
"TOKEN_TYPE_MINUS",
"TOKEN_TYPE_EQUAL",
};
*/
typedef struct Token_ Token;
typedef struct Lexer_ Lexer;
Lexer *Lexer_init(Lexer*, FILE*, int);
void Lexer_final(Lexer*);
int Lexer_get(Lexer*);
int Lexer_put(Lexer*, int);
void Lexer_skip(Lexer*);
int Lexer_tokenizer(Lexer*, Token*);
void Lexer_tokenizer_num(Lexer*, Token*);
struct Token_ {
int num;
TokenType type;
};
struct Lexer_ {
FILE* file;
int close;
int buf;
int is_buf;
};
Lexer *Lexer_init(Lexer *self, FILE* file, int close) {
self->file = file;
self->close = close;
self->is_buf = 0;
return self;
}
void Lexer_final(Lexer *self) {
if (self->file && self->close) {
}
}
int Lexer_get(Lexer* self) {
if (EOF != self->buf && !self->is_buf) {
return self
->buf
= fgetc(self
->file
); }
self->is_buf = 0;
return self->buf;
}
int Lexer_put(Lexer* self, int c) {
if (self->is_buf) {
fprintf(stderr
, "ERROR!: Lexer_put: buffer full.\n"); return 1;
}
self->is_buf = 1;
self->buf = c;
return 0;
}
int Lexer_tokenizer(Lexer* self, Token *token) {
if (NULL == token) {
fprintf(stderr
, "ERROR!: Lexer_tokenizer: failed malloc.\n"); return 1;
}
Lexer_skip(self);
int c;
switch (c = Lexer_get(self)) {
case EOF: token->type = TOKEN_TYPE_EOF; break;
case ';': token->type = TOKEN_TYPE_DELIM; break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
token->type = TOKEN_TYPE_NUM;
token->num = c - '0';
Lexer_tokenizer_num(self, token);
break;
case 'x': case 'X': token->type = TOKEN_TYPE_X; break;
case '+': token->type = TOKEN_TYPE_PLUS; break;
case '-': token->type = TOKEN_TYPE_MINUS; break;
case '=': token->type = TOKEN_TYPE_EQUAL; break;
default:
Lexer_put(self, c);
return 1;
}
return 0;
}
void Lexer_skip(Lexer* self) {
int c;
for (;;) {
switch (c = Lexer_get(self)) {
case ' ': case '\t': case '\r': case '\n': break;
default: Lexer_put(self, c); return;
}
}
}
void Lexer_tokenizer_num(Lexer* self, Token* token) {
int c;
for (;;) {
switch (c = Lexer_get(self)) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
token->num *= 10;
token->num += c - '0';
break;
default:
Lexer_put(self, c);
return;
}
}
}
typedef enum CellType_ {
CELL_TYPE_TRIPLE,
CELL_TYPE_NUM,
CELL_TYPE_X,
CELL_TYPE_MINUS_X,
} CellType;
static const char* CELL_TYPE_STR[4] = {
"CELL_TYPE_TRIPLE",
"CELL_TYPE_NUM",
"CELL_TYPE_X",
"CELL_TYPE_MINUS_X",
};
typedef struct Cell_ Cell;
typedef enum Operator_ {
OP_PLUS,
OP_MINUS,
OP_EQUAL,
} Operator;
typedef struct Triple_ Triple;
void Cell_fput(FILE*, Cell*);
Cell* Cell_new_triple(Triple*);
Cell* Cell_new_num(int);
Cell* Cell_new_x(void);
Cell* Cell_new_minus_x(void);
void Cell_delete(Cell*);
int Cell_minus(Cell*);
int Cell_swap(Cell*);
int Cell_solver(Cell*);
int Cell_count_x(Cell*);
int Cell_eval(Cell*);
void Triple_fput(FILE*, Triple*);
Triple* Triple_new(Operator, Cell*, Cell*);
void Triple_delete(Triple*);
struct Cell_ {
CellType type;
union {
Triple *triple;
int num;
} val;
};
struct Triple_ {
Operator op;
Cell* lhs;
Cell* rhs;
};
void Cell_fput(FILE *stream, Cell *self) {
if (NULL == self) {
} else {
switch (self->type) {
case CELL_TYPE_TRIPLE:
Triple_fput(stream, self->val.triple);
break;
case CELL_TYPE_NUM:
fprintf(stream
, "%i", self
->val.
num); break;
case CELL_TYPE_X:
break;
case CELL_TYPE_MINUS_X:
break;
default:
break;
}
}
}
Cell* Cell_new_triple(Triple* triple) {
Cell
*self
= malloc(sizeof(Cell
)); self->type = CELL_TYPE_TRIPLE;
self->val.triple = triple;
return self;
}
Cell* Cell_new_num(int num) {
Cell
*self
= malloc(sizeof(Cell
)); self->type = CELL_TYPE_NUM;
self->val.num = num;
return self;
}
Cell* Cell_new_x(void) {
Cell
*self
= malloc(sizeof(Cell
)); self->type = CELL_TYPE_X;
return self;
}
Cell* Cell_new_minus_x(void) {
Cell
*self
= malloc(sizeof(Cell
)); self->type = CELL_TYPE_MINUS_X;
return self;
}
void Cell_delete(Cell *self) {
if (NULL == self) { return; }
switch (self->type) {
case CELL_TYPE_TRIPLE:
Triple_delete(self->val.triple);
break;
case CELL_TYPE_NUM:
case CELL_TYPE_X:
default:
break;
}
}
int Cell_minus(Cell* self) {
switch (self->type) {
case CELL_TYPE_TRIPLE:
Cell_minus(self->val.triple->lhs);
Cell_minus(self->val.triple->rhs);
break;
case CELL_TYPE_NUM: self->val.num *= -1; break;
case CELL_TYPE_X: self->type = CELL_TYPE_MINUS_X; break;
case CELL_TYPE_MINUS_X: self->type = CELL_TYPE_X; break;
}
return 0;
}
int Cell_swap(Cell* self) {
if (CELL_TYPE_TRIPLE != self->type) {
fprintf(stderr
, "ERROR!: Cell_solver: invalid swap.\n"); return 1;
}
if (OP_MINUS == self->val.triple->op) {
Cell_minus(self->val.triple->rhs);
self->val.triple->op = OP_PLUS;
}
Cell* tmp = self->val.triple->lhs;
self->val.triple->lhs = self->val.triple->rhs;
self->val.triple->rhs = tmp;
return 0;
}
int Cell_solver(Cell *self) {
Cell_fput
(stdout
, self
); fputc('\n', stdout
); if (CELL_TYPE_TRIPLE != self->type ||
OP_EQUAL != self->val.triple->op ||
1 != Cell_count_x(self)) {
fprintf(stderr
, "ERROR!: Cell_solver: invalid cell.\n"); return 1;
}
if (0 == Cell_count_x(self->val.triple->lhs)) {
Cell_swap(self);
}
while (CELL_TYPE_TRIPLE == self->val.triple->lhs->type) {
if (0 == Cell_count_x(self->val.triple->lhs->val.triple->lhs)) {
Cell_swap(self->val.triple->lhs);
}
switch (self->val.triple->lhs->val.triple->op) {
case OP_PLUS: {
Cell* tmp = self->val.triple->lhs->val.triple->rhs;
self->val.triple->lhs = self->val.triple->lhs->val.triple->lhs;
Triple* triple = Triple_new(OP_MINUS, self->val.triple->rhs, NULL);
triple->rhs = tmp;
self->val.triple->rhs = Cell_new_triple(triple);
break;
}
case OP_MINUS: {
Cell* tmp = self->val.triple->lhs->val.triple->rhs;
self->val.triple->lhs = self->val.triple->lhs->val.triple->lhs;
Triple* triple = Triple_new(OP_PLUS, self->val.triple->rhs, NULL);
triple->rhs = tmp;
self->val.triple->rhs = Cell_new_triple(triple);
break;
}
default:
fprintf(stderr
, "ERROR!: Cell_solver: invalid cell.\n"); return 1;
}
}
if (CELL_TYPE_MINUS_X == self->val.triple->lhs->type) {
Cell_minus(self->val.triple->rhs);
self->val.triple->lhs->type = CELL_TYPE_X;
}
Cell_fput
(stdout
, self
); fputc('\n', stdout
); printf("x = %i\n\n", Cell_eval
(self
->val.
triple->rhs
)); return 0;
}
int Cell_count_x(Cell *self) {
switch (self->type) {
case CELL_TYPE_TRIPLE:
return (Cell_count_x(self->val.triple->lhs) +
Cell_count_x(self->val.triple->rhs));
case CELL_TYPE_X:
case CELL_TYPE_MINUS_X:
return 1;
default:
return 0;
}
}
int Cell_eval(Cell *self) {
switch (self->type) {
case CELL_TYPE_TRIPLE:
switch (self->val.triple->op) {
case OP_PLUS: return (Cell_eval(self->val.triple->lhs) +
Cell_eval(self->val.triple->rhs));
case OP_MINUS: return (Cell_eval(self->val.triple->lhs) -
Cell_eval(self->val.triple->rhs));
default:
fprintf(stderr
, "ERROR!: Cell_eval: invalid cell op.\n"); return 1;
}
break;
case CELL_TYPE_NUM:
return self->val.num;
case CELL_TYPE_X:
case CELL_TYPE_MINUS_X:
default:
fprintf(stderr
, "ERROR!: Cell_eval: invalid cell %s.\n", CELL_TYPE_STR[self->type]);
return 1;
}
}
static const char* const OP_STR[3] = { "+", "-", "=", };
void Triple_fput(FILE *stream, Triple *self) {
fprintf(stream
, "(%s, ", OP_STR
[self
->op
]); Cell_fput(stream, self->lhs);
Cell_fput(stream, self->rhs);
}
Triple* Triple_new(Operator op, Cell* lhs, Cell* rhs) {
Triple
*self
= malloc(sizeof(Triple
)); self->op = op;
self->lhs = lhs;
self->rhs = rhs;
return self;
}
void Triple_delete(Triple *self) {
if (NULL == self) { return; }
Cell_delete(self->lhs);
Cell_delete(self->rhs);
}
typedef struct Parser_ Parser;
struct Parser_ {
Lexer lexer;
Token token[2];
int buf_cnt;
};
Parser *Parser_init(Parser*, FILE*, int);
void Parser_final(Parser*);
Token *Parser_get(Parser*);
int Parser_put(Parser*, Token*);
int Parser_start(Parser*);
Cell *Parser_assign(Parser*);
Cell *Parser_expr(Parser*);
Cell *Parser_expr_tail(Parser*);
Cell *Parser_signed(Parser*);
Cell *Parser_elem(Parser*);
int parse_file(FILE*, int);
int parse_buffer(const char*, size_t len);
int parse_str(const char*);
Parser *Parser_init(Parser *self, FILE *file, int close) {
Lexer_init(&self->lexer, file, close);
self->buf_cnt = 0;
return self;
}
void Parser_final(Parser *self) {
if (NULL == self) { return; }
Lexer_final(&self->lexer);
}
Token *Parser_get(Parser* self) {
if (0 == self->buf_cnt) {
if (0 != Lexer_tokenizer(&self->lexer, &self->token[0])) {
fprintf(stderr
, "ERROR!: Parser_get: failed Lexer_tokenizer.\n"); return NULL;
}
return &self->token[0];
}
return &self->token[self->buf_cnt--];
}
int Parser_put(Parser* self, Token* token) {
if (1 <= self->buf_cnt) {
fprintf(stderr
, "ERROR!: Parser_put: buffer full.\n"); return 1;
}
memcpy(&self
->token
[++self
->buf_cnt
], token
, sizeof(Token
)); return 0;
}
int Parser_start(Parser *self) {
for(;;) {
Cell* cell = Parser_assign(self);
if (!cell) { return 1; }
// Cell_fput(stdout, cell); putc('\n', stdout);
Cell_solver(cell);
Cell_delete(cell);
}
}
Cell *Parser_assign(Parser *self) {
Cell* cell = Parser_expr(self);
if(!cell) { return NULL; }
Token *token = Parser_get(self);
switch (token->type) {
case TOKEN_TYPE_EQUAL:
cell = Cell_new_triple(Triple_new(OP_EQUAL, cell, NULL));
break;
default:
fprintf(stderr
, "ERROR!: Parser_assign: invalid cell.\n"); Cell_delete(cell);
return NULL;
}
Cell* rhs = Parser_expr(self);
if(!rhs) {
fprintf(stderr
, "ERROR!: Parser_assign: invalid cell.\n"); Cell_delete(cell);
return NULL;
}
cell->val.triple->rhs = rhs;
token = Parser_get(self);
switch (token->type) {
case TOKEN_TYPE_DELIM:
break;
default:
fprintf(stderr
, "ERROR!: Parser_assign: invalid cell.\n"); Cell_delete(cell);
return NULL;
}
return cell;
}
Cell *Parser_expr(Parser *self) {
Cell* cell = Parser_signed(self);
if(!cell) { return NULL; }
for (;;) {
Cell* tail = Parser_expr_tail(self);
if(!tail) { break; }
tail->val.triple->lhs = cell;
cell = tail;
}
return cell;
}
Cell *Parser_expr_tail(Parser *self) {
Cell* cell = NULL;
Token *token = Parser_get(self);
switch (token->type) {
case TOKEN_TYPE_PLUS: {
Cell* rhs = Parser_signed(self);
if (NULL == rhs) { Parser_put(self, token); return NULL; }
cell = Cell_new_triple(Triple_new(OP_PLUS, NULL, rhs));
break;
}
case TOKEN_TYPE_MINUS: {
Cell* rhs = Parser_signed(self);
if (NULL == rhs) { Parser_put(self, token); return NULL; }
cell = Cell_new_triple(Triple_new(OP_MINUS, NULL, rhs));
break;
}
default:
Parser_put(self, token);
return NULL;
}
return cell;
}
Cell *Parser_signed(Parser *self) {
Token *token = Parser_get(self);
switch (token->type) {
case TOKEN_TYPE_NUM: return Cell_new_num(token->num);
case TOKEN_TYPE_X: return Cell_new_x();
case TOKEN_TYPE_PLUS: {
Cell* cell = Parser_elem(self);
if(!cell) { Parser_put(self, token); return NULL; }
return cell;
}
case TOKEN_TYPE_MINUS: {
Cell* cell = Parser_elem(self);
if(!cell) { Parser_put(self, token); return NULL; }
switch (cell->type) {
case CELL_TYPE_NUM: cell->val.num *= -1; break;
case CELL_TYPE_X: cell->type = CELL_TYPE_MINUS_X; break;
default:
fprintf(stderr
, "ERROR!: Parser_signed: invalid cell.\n"); Cell_delete(cell);
return NULL;
}
return cell;
}
default: Parser_put(self, token); return NULL;
}
}
Cell *Parser_elem(Parser *self) {
Token *token = Parser_get(self);
switch (token->type) {
case TOKEN_TYPE_NUM: return Cell_new_num(token->num);
case TOKEN_TYPE_X: return Cell_new_x();
default: Parser_put(self, token); return NULL;
}
}
int parse_file(FILE* file, int close) {
Parser parser;
Parser_init(&parser, file, close);
Parser_start(&parser);
Parser_final(&parser);
return 0;
}
int parse_buffer(const char* buffer, size_t length) {
fwrite(buffer
, 1, length
, file
); fseek(file
, 0, SEEK_SET
); return parse_file(file, 1);
}
int parse_str(const char* str) {
return parse_buffer
(str
, strlen(str
)); }
int main(int argc, char* argv[]) {
//parse_str("5 - 6 = x; x + 7 = 32; 4 - x = 43; 1 + -3 = 4 - 7 + -x;");
parse_file(stdin, 0);
return 0;
}