Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- enum TOKEN_ID
- {
- NUM,
- LBRACKET,
- RBRACKET,
- LPAREN,
- RPAREN,
- COMMA,
- PLUS,
- MINUS,
- MUL
- };
- typedef struct input
- {
- enum TOKEN_ID id;
- char *s;
- int eof;
- int num;
- } input;
- typedef struct result
- {
- double val;
- int is_vector;
- size_t n;
- double *vals;
- } result;
- void
- error(char *msg)
- {
- fprintf(stderr, "%s\n", msg);
- exit(1);
- }
- void
- getsym(input *i)
- {
- for (;;) {
- if (*(i->s) == '\0') {
- i->eof = 1;
- return;
- }
- if (isspace(*(i->s))) {
- i->s++;
- } else {
- break;
- }
- }
- if (isdigit(*(i->s))) {
- size_t l = 0;
- char snum[20];
- do {
- snum[l] = *(i->s);
- l++;
- if (l > sizeof(snum)) {
- error("Number too big");
- }
- i->s++;
- if (*(i->s) == '\0') {
- i->eof = 1;
- break;
- }
- } while (isdigit(*(i->s)));
- snum[l] = '\0';
- i->num = atoi(snum);
- i->id = NUM;
- return;
- }
- #define SINGLE_SYM_TOKEN(SYM, ID)\
- if (*(i->s) == SYM) {\
- i->id = ID;\
- i->s++;\
- return;\
- }
- SINGLE_SYM_TOKEN('[', LBRACKET)
- SINGLE_SYM_TOKEN(']', RBRACKET)
- SINGLE_SYM_TOKEN('(', LPAREN)
- SINGLE_SYM_TOKEN(')', RPAREN)
- SINGLE_SYM_TOKEN('+', PLUS)
- SINGLE_SYM_TOKEN('-', MINUS)
- SINGLE_SYM_TOKEN('*', MUL)
- SINGLE_SYM_TOKEN(',', COMMA)
- #undef SINGLE_SYM_TOKEN
- error("Unknown token");
- }
- int
- accept(input *i, enum TOKEN_ID id)
- {
- if (i->id == id) {
- getsym(i);
- return 1;
- }
- return 0;
- }
- int
- expect(input *i, enum TOKEN_ID id)
- {
- if (accept(i, id)) {
- return 1;
- }
- error("Unexpected symbol");
- return 0;
- }
- void
- result_init(result *r)
- {
- r->is_vector = 0;
- r->n = 0;
- r->val = 0.0;
- r->vals = NULL;
- }
- void
- result_free(result *r)
- {
- if (r->vals) {
- free(r->vals);
- r->vals = NULL;
- }
- r->is_vector = 0;
- }
- void
- result_dump(result *a)
- {
- size_t i;
- if (!a->is_vector) {
- printf("%f\n", a->val);
- return;
- }
- printf("[");
- for (i=0; i<a->n; i++) {
- printf("%f", a->vals[i]);
- if (i < (a->n - 1)) {
- printf(", ");
- }
- }
- printf("]\n");
- }
- void
- result_swap(result *a, result *b)
- {
- result tmp;
- tmp = *a;
- *a = *b;
- *b = tmp;
- }
- void
- vector_push(result *r, int v)
- {
- r->is_vector = 1;
- r->n++;
- r->vals = realloc(r->vals, r->n * sizeof(r->val));
- r->vals[r->n - 1] = v;
- }
- void
- result_mul(result *a, result *b)
- {
- size_t i;
- if (a->is_vector && b->is_vector) {
- error("Can't mul vector by vector");
- }
- if (!a->is_vector && !b->is_vector) {
- a->val *= b->val;
- return;
- }
- if (b->is_vector) {
- result_swap(a, b);
- }
- for (i=0; i<a->n; i++) {
- a->vals[i] *= b->val;
- }
- }
- void
- result_inv(result *a)
- {
- if (!a->is_vector) {
- a->val = -a->val;
- } else {
- size_t i;
- for (i=0; i<a->n; i++) {
- a->vals[i] = -a->vals[i];
- }
- }
- }
- void
- result_plus(result *a, result *b)
- {
- size_t i;
- if (!a->is_vector && !b->is_vector) {
- a->val += b->val;
- return;
- }
- if (a->is_vector && b->is_vector) {
- if (a->n < b->n) {
- result_swap(a, b);
- }
- for (i=0; i<b->n; i++) {
- a->vals[i] += b->vals[i];
- }
- } else {
- error("Can't add scalar to vector");
- }
- }
- void
- result_minus(result *a, result *b)
- {
- result_inv(b);
- result_plus(a, b);
- }
- result expression(input *i);
- result
- vector(input *i)
- {
- result r, tmp;
- result_init(&r);
- tmp = expression(i);
- if (tmp.is_vector) {
- error("Subvectors not allowed");
- }
- vector_push(&r, tmp.val);
- while (i->id != RBRACKET) {
- expect(i, COMMA);
- tmp = expression(i);
- if (tmp.is_vector) {
- error("Subvectors not allowed");
- }
- vector_push(&r, tmp.val);
- }
- return r;
- }
- result
- factor(input *i)
- {
- result r;
- result_init(&r);
- if (accept(i, NUM)) {
- r.val = i->num;
- } else if (accept(i, LBRACKET)) {
- r = vector(i);
- expect(i, RBRACKET);
- } else if (accept(i, LPAREN)) {
- r = expression(i);
- expect(i, RPAREN);
- } else {
- error("Syntax error");
- }
- return r;
- }
- result
- term(input *i)
- {
- result left, r;
- left = factor(i);
- while (i->id == MUL) {
- getsym(i);
- r = factor(i);
- result_mul(&left, &r);
- result_free(&r);
- }
- return left;
- }
- result
- expression(input *i)
- {
- int inv = 0;
- result left, r;
- if (i->id == PLUS || i->id == MINUS) {
- if (i->id == MINUS) inv = 1;
- getsym(i);
- }
- left = term(i);
- if (inv) {
- result_inv(&left);
- }
- while (i->id == PLUS || i->id == MINUS) {
- int sign = i->id;
- getsym(i);
- r = term(i);
- if (sign == MINUS) {
- result_minus(&left, &r);
- } else {
- result_plus(&left, &r);
- }
- result_free(&r);
- }
- return left;
- }
- int
- main()
- {
- input i;
- result r;
- i.eof = 0;
- i.s = "5 * [1,2,3] + ( 5 * [3,2,1] - [1,2]) + [1,2,3,4,5,6]";
- getsym(&i);
- r = expression(&i);
- if (!i.eof) {
- error("Incorrect expression");
- }
- result_dump(&r);
- result_free(&r);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment