summaryrefslogtreecommitdiff
path: root/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'interface.c')
-rw-r--r--interface.c234
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"));
+ }
+ }
+}