diff options
Diffstat (limited to 'lib/parser.c')
-rw-r--r-- | lib/parser.c | 483 |
1 files changed, 247 insertions, 236 deletions
diff --git a/lib/parser.c b/lib/parser.c index 7cc242d..cf2eab3 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -18,8 +18,8 @@ typedef unsigned char op_t; typedef struct operator_t { - op_t op; - int pri, func; + op_t op; + int pri, func; } operator_t; static op_t pile_operators[PILEOP_MAX]; @@ -30,258 +30,268 @@ 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} + {',', 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; + int i; - for (i = 0; operators[i].op != 255; i++) { - if (operators[i].op == op) - return operators[i]; - } + for (i = 0; operators[i].op != 255; i++) { + if (operators[i].op == op) + return operators[i]; + } - 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; + return get_op(op).pri; } static int get_func(op_t op) { - return get_op(op).func; + 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; + 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; + 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")); + 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; + 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]++; - } + 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; + 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")); + 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; - } - } + 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; + } + } + 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")); + 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 @@ -290,62 +300,63 @@ void parse_line(char *line) void push_pile(char *word) { - printf("%s ", 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); + 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); + 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 |