#include #include #ifdef HAVE_CONFIG_H #include "config.h" #else #define _(x) x #endif #include "exceptions.h" #include "parser.h" #include "assembler.h" /*******************************\ * * * Parser * * * \*******************************/ typedef unsigned char op_t; typedef struct operator_t { op_t op; int pri, func; } operator_t; static op_t pile_operators[PILEOP_MAX]; static int pile_nestedcall[PILECALL_MAX]; static int pileop_pos = 0, pilecall_pos = 0; /* La liste des opérateurs reconnus par le parser */ static operator_t operators[] = { {',', 0, OP_NEST}, {'+', 2, OP_PLUS}, {'-', 2, OP_MOINS}, {'*', 3, OP_MUL}, {'/', 3, OP_DIV}, {'%', 3, OP_MOD}, {'+' + 128, 4, OP_PLUS_UNARY}, {'-' + 128, 4, OP_MOINS_UNARY}, {'(', 5, OP_FUNC_CALL}, {'(' + 128, 5, OP_LPAREN}, {'[', 5, OP_DECAL}, {'[' + 128, 5, OP_DIRECT}, {255, -1, -1} }; /* Fonction interne: convertit un operateur en sa structure */ static 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]; } /* Fonctions internes de lectures sur la structure */ static int get_pri(op_t op) { return get_op(op).pri; } static int get_func(op_t op) { return get_op(op).func; } /* Focntions internes d'empilement / dépilement */ static op_t get_last_op(void) { if (pileop_pos) return pile_operators[pileop_pos - 1]; else return -1; } static op_t pop_op(void) { if (pileop_pos) return pile_operators[--pileop_pos]; return -1; } static 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")); } static int pop_call(void) { if (pilecall_pos) return pile_nestedcall[--pilecall_pos]; return -1; } static void increment_call(void) { if (pilecall_pos) { if (pile_nestedcall[pilecall_pos - 1] != -1) pile_nestedcall[pilecall_pos - 1]++; } } static int get_last_call(void) { if (pilecall_pos) return pile_nestedcall[pilecall_pos - 1]; return -1; } static void push_call(int call) { if (pilecall_pos != PILECALL_MAX) pile_nestedcall[pilecall_pos++] = call; else exception(-1, _("Too many nested functions calls in expression.\n")); } /* Cette fonction lit un "mot" sur la chaine line et renvoit le nouveau pointeur */ static char *getword(char *line, char *p) { char o = 0, *d = line, instring = 0, gotbslash = 0; do { if (instring) { o = *(p++) = *line; if (!gotbslash) { switch (instring) { case 1: if (*line == '\'') { instring = 0; } break; case 2: if (*line == '"') { instring = 0; } break; } if (*line == '\\') gotbslash = 1; } else { gotbslash = 0; } } else { if (*(line) == '\'') { o = *(p++) = *line; instring = 1; } else if (*(line) == '"') { o = *(p++) = *line; instring = 2; } else { if (*(line) != ' ' && *(line) != '\t') { o = *(p++) = *line; } else if (d != line) { *p = '\0'; return line; } } } line++; } while (((*line) && (*line != ')') && (*line != ']') && (*line != ';') && (get_func(*line) == -1) && (get_func(o) == -1)) || (instring)); *p = '\0'; return line; } /* Cette fonction va parcourire une chaine afin d'appeler les fonction push_pule() et act_pile() */ void parse_line(char *line) { char buffer[BUFSIZ], imm[BUFSIZ], *d = line; op_t op; int got_unary = 128, nbrargs; sprintf(buffer, "Read line '%s'", line); pushcontext(buffer); while (*line) { line = getword(line, buffer); sprintf(imm, "Analysing word '%s' at position %i", buffer, line - d); pushcontext(imm); if (get_func(buffer[0]) != -1) { /* Le mot lut est un operateur, on agit sur la pile */ buffer[0] += got_unary; if (got_unary) { } if (get_pri(buffer[0]) == -1) { if (got_unary) { exception(-1, _("Invalid unary operator")); } else { exception(-1, _("Invalid binary operator")); } } while (get_pri(get_last_op()) >= get_pri(buffer[0]) && (((get_last_op() & 127) != '(') && ((get_last_op() & 127) != '['))) { act_pile(get_func(pop_op())); got_unary = 0; } 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] == ')') || (buffer[0] == ']')) { /* Le mot lut est un opérateur spécial, on vide la pile */ switch (buffer[0]) { case ';': /* Equivalent a fin de ligne */ while (pileop_pos) { op = pop_op(); if (op == '(') exception(-1, _("Parse error: too much left parenthesis")); act_pile(get_func(op)); } popcontext(); popcontext(); return; case ')': /* Fin de parenthese (Appel de fonction ou expression mathématique) */ while (1) { if (!pileop_pos) exception(-1, _("Parse error: too much right parenthesis")); op = pop_op(); if (((op & 127) == '(')) break; if (((op & 127) == '[')) exception(-1, _("Parse error: enclosure mismatch")); act_pile(get_func(op)); } if (op == '(') { nbrargs = pop_call(); sprintf(imm, "%i", nbrargs); push_pile(imm); act_pile(get_func(op)); } got_unary = 0; break; case ']': /* Fin d'opérateur de décalage */ while (1) { if (!pileop_pos) exception(-1, _("Parse error: too much right parenthesis")); op = pop_op(); if (((op & 127) == '[')) break; if (((op & 127) == '(')) exception(-1, _("Parse error: enclosure mismatch")); act_pile(get_func(op)); } 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] == '_') || (buffer[0] == '"') || (buffer[0] == '\'') || (buffer[0] == '.') || (buffer[0] == '#') || (buffer[0] == '?')) { /* Dans tous les autres cas, on a reçu un symbole, on le pose sur la pile */ push_pile(buffer); got_unary = 0; if (!get_last_call()) increment_call(); } else if (buffer[0]) { exception(-1, _("Invalid character")); } popcontext(); } popcontext(); } #ifndef HAVE_CONFIG_H /* Les quelques fonctions de test, lorsque le parser est compilé en dehors du projet. */ void push_pile(char *word) { printf("%s ", word); } void act_pile(int func) { char op; switch (func) { case OP_PLUS: op = '+'; break; case OP_MOINS: op = '-'; break; case OP_DIV: op = '/'; break; case OP_MUL: op = '*'; break; case OP_PLUS_UNARY: op = '\0'; break; case OP_MOINS_UNARY: op = '|'; break; case OP_FUNC_CALL: op = '@'; break; case OP_DECAL: op = '['; break; case OP_DIRECT: op = '{'; break; } printf("%c ", op); } void main(void) { parse_line("ADD R18, R20, 39;"); printf("\n\n"); fflush(stdout); parse_line("MOV R31, Bidule[48 + R12];"); printf("\n\n"); fflush(stdout); parse_line("MOV R12, [R3];"); printf("\n\n"); fflush(stdout); parse_line("MOV R22, Truc[(3+2)*8];"); printf("\n\n"); fflush(stdout); parse_line("Trucmuche DB \"Test de chaîne complète avec des opérateurs comme le + et le - ...\""); printf("\n\n"); fflush(stdout); } #endif