diff options
author | biouman <biouman> | 2001-04-27 04:12:25 +0000 |
---|---|---|
committer | biouman <biouman> | 2001-04-27 04:12:25 +0000 |
commit | 4db12b8121c0b32df8b8671045013c857beb191f (patch) | |
tree | 15489f56132610576bd5cd860d38d8b759f64482 /interface.c |
Diffstat (limited to 'interface.c')
-rw-r--r-- | interface.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/interface.c b/interface.c new file mode 100644 index 0000000..419e624 --- /dev/null +++ b/interface.c @@ -0,0 +1,234 @@ +/* + * + * Interpreteur de ligne de commande + * + */ + +#include <stdio.h> +#include <limits.h> +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif +#include "interface.h" +#include "exceptions.h" +#include "pile.h" + + + +typedef unsigned char op_t; + +typedef struct operator_t { + op_t op; + int pri, func; +} operator_t; + +op_t pile_operators[PILEOP_MAX]; +int pile_nestedcall[PILECALL_MAX]; + +int pileop_pos = 0, pilecall_pos = 0; + +operator_t operators[] = { + {',', 0, OP_NEST}, + {'+', 2, OP_PLUS}, + {'-', 2, OP_MOINS}, + {'*', 3, OP_MUL}, + {'/', 3, OP_DIV}, + {'%', 3, OP_MOD}, + {'^', 4, OP_EXP}, + {'+' + 128, 5, OP_PLUS_UNARY}, + {'-' + 128, 5, OP_MOINS_UNARY}, + {'=', 1, OP_ASSIGN}, + {'(', 6, OP_FUNC_CALL}, + {'(' + 128, 6, OP_LPAREN}, + {255, -1, -1} +}; + +operator_t get_op(op_t op) +{ + int i; + + for (i = 0; operators[i].op != 255; i++) { + if (operators[i].op == op) + return operators[i]; + } + + return operators[i]; +} + +int get_pri(op_t op) +{ + return get_op(op).pri; +} + +int get_func(op_t op) +{ + return get_op(op).func; +} + +op_t get_last_op(void) +{ + if (pileop_pos) + return pile_operators[pileop_pos - 1]; + else + return -1; +} + +op_t pop_op(void) +{ + if (pileop_pos) + return pile_operators[--pileop_pos]; + return -1; +} + +void push_op(op_t op) +{ + if (pileop_pos != PILEOP_MAX) + pile_operators[pileop_pos++] = op; + else + exception(-1, _("Too many nested operators in expression.\n")); + +} + +int pop_call(void) +{ + if (pilecall_pos) + fprintf(stderr, "Dépilement du dernier appel de fonction: %i\n", + pile_nestedcall[pilecall_pos - 1]); + return pile_nestedcall[--pilecall_pos]; + return -1; +} + +void increment_call(void) +{ + if (pilecall_pos) { + fprintf(stderr, "Incrément du dernier appel de fonction: %i\n", + pile_nestedcall[pilecall_pos - 1]); + if (pile_nestedcall[pilecall_pos - 1] != -1) + pile_nestedcall[pilecall_pos - 1]++; + } +} + +int get_last_call(void) +{ + if (pilecall_pos) + return pile_nestedcall[pilecall_pos - 1]; + return -1; +} + +void push_call(int call) +{ + fprintf(stderr, "Empilement d'un appel de fonction: %i\n", call); + if (pilecall_pos != PILECALL_MAX) + pile_nestedcall[pilecall_pos++] = call; + else + exception(-1, _("Too many nested functions calls in expression.\n")); +} + +char *getword(char *line, char *p) +{ + char o; + + do { + if (*(line) != ' ') { + o = *(p++) = *line; + fprintf(stderr, "getword(): a trouvé le caractère '%c'\n", o); + } + line++; + } while ((*line) && (*line != ')') && (*line != ';') && (get_func(*line) == -1) + && (get_func(o) == -1)); + *p = '\0'; + return line; +} + +int parse_line(char *line) +{ + char buffer[BUFSIZ]; + op_t op; + int got_unary = 128, nbrargs; + + fprintf(stderr, "Analyse de: \"%s\"...\n\n", line); + while (*line) { + line = getword(line, buffer); + fprintf(stderr, "parse_line(): getword a trouvé le mot \"%s\"\n", buffer); + if (get_func(buffer[0]) != -1) { + fprintf(stderr, "Il s'agit d'un opérateur.\n"); + buffer[0] += got_unary; + if (got_unary) { + fprintf(stderr, "Opérateur de type unaire\n"); + } + if (get_pri(buffer[0]) == -1) { + if (got_unary) { + exception(-1, _("Invalid unary operator")); + } else { + exception(-1, _("Invalid binary operator")); + } + } + fprintf(stderr, "Priorité du dernier op: %i, priorité actu: %i\n", + get_pri(get_last_op()), get_pri(buffer[0])); + while (get_pri(get_last_op()) >= get_pri(buffer[0]) + && ((get_last_op() & 127) != '(')) { + fprintf(stderr, + "Il y a un opérateur plus important sur la file.\n"); + act_pile(get_func(pop_op())); + got_unary = 0; + fprintf(stderr, "Priorité du dernier op: %i, priorité actu: %i\n", + get_pri(get_last_op()), get_pri(buffer[0])); + } + fprintf(stderr, "Mise sur la file\n"); + if (buffer[0] == '(') { + push_call(0); + } + if (buffer[0] == ',') { + increment_call(); + } else + push_op(buffer[0]); + got_unary = 128; + } else if ((buffer[0] == ';') || (buffer[0] == ')')) { + fprintf(stderr, "Caractère spécial\n"); + switch (buffer[0]) { + case ';': + fprintf(stderr, "Vidage complet de la file (fin de commande).\n"); + while (pileop_pos) { + op = pop_op(); + if (op == '(') + exception(-1, + _ + ("Parse error: too much left parenthesis")); + act_pile(get_func(op)); + } + break; + case ')': + fprintf(stderr, "Vidage de la file jusqu'à '(' car ')' trouvée.\n"); + while (1) { + if (!pileop_pos) + exception(-1, + _ + ("Parse error: too much right parenthesis")); + op = pop_op(); + if (((op & 127) == '(')) + break; + act_pile(get_func(op)); + } + if (op == '(') { + nbrargs = pop_call(); + push_pile_int(nbrargs); + act_pile(get_func(op)); + } + got_unary = 0; + break; + } + } else if (((buffer[0] >= 'A') && (buffer[0] <= 'Z')) + || ((buffer[0] >= 'a') && (buffer[0] <= 'z')) + || ((buffer[0] >= '0') && (buffer[0] <= '9')) || (buffer[0] == '_')) { + fprintf(stderr, "Symbole.\n"); + push_pile(buffer); + got_unary = 0; + if (!get_last_call()) + increment_call(); + } else if (buffer[0]) { + exception(-1, _("Invalid character")); + } + } +} |