summaryrefslogtreecommitdiff
path: root/lib/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/parser.c')
-rw-r--r--lib/parser.c151
1 files changed, 96 insertions, 55 deletions
diff --git a/lib/parser.c b/lib/parser.c
index ee3e64c..2a9edd1 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -4,11 +4,16 @@
#include "config.h"
#else
#define _(x) x
-void exception(int, char *);
#endif
#include "exceptions.h"
#include "parser.h"
+#include "assembler.h"
+/*******************************\
+* *
+* Parser *
+* *
+\*******************************/
typedef unsigned char op_t;
@@ -22,8 +27,10 @@ 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},
+ {',', 0, OP_NEST},
{'+', 2, OP_PLUS},
{'-', 2, OP_MOINS},
{'*', 3, OP_MUL},
@@ -37,6 +44,8 @@ static operator_t operators[] = {
{255, -1, -1}
};
+/* Fonction interne: convertit un operateur en sa structure */
+
static operator_t get_op(op_t op)
{
int i;
@@ -49,6 +58,8 @@ static operator_t get_op(op_t op)
return operators[i];
}
+/* Fonctions internes de lectures sur la structure */
+
static int get_pri(op_t op)
{
return get_op(op).pri;
@@ -59,6 +70,8 @@ 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)
@@ -87,20 +100,22 @@ static int pop_call(void)
{
if (pilecall_pos)
return pile_nestedcall[--pilecall_pos];
- return -1;
+ 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 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)
@@ -111,6 +126,8 @@ static void push_call(int call)
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;
@@ -120,18 +137,19 @@ static char *getword(char *line, char *p)
o = *(p++) = *line;
if (!gotbslash) {
switch (instring) {
- case 1:
- if (*line == '\'') {
- instring = 0;
- }
- break;
- case 2:
- if (*line == '"') {
- instring = 0;
- }
- break;
+ case 1:
+ if (*line == '\'') {
+ instring = 0;
+ }
+ break;
+ case 2:
+ if (*line == '"') {
+ instring = 0;
+ }
+ break;
}
- if (*line == '\\') gotbslash = 1;
+ if (*line == '\\')
+ gotbslash = 1;
} else {
gotbslash = 0;
}
@@ -143,7 +161,7 @@ static char *getword(char *line, char *p)
o = *(p++) = *line;
instring = 2;
} else {
- if (*(line) != ' ') {
+ if (*(line) != ' ' && *(line) != '\t') {
o = *(p++) = *line;
} else if (d != line) {
*p = '\0';
@@ -153,20 +171,28 @@ static char *getword(char *line, char *p)
}
line++;
} while (((*line) && (*line != ')') && (*line != ']') && (*line != ';') && (get_func(*line) == -1)
- && (get_func(o) == -1)) || (instring));
+ && (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];
+ 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) {
}
@@ -177,28 +203,35 @@ void parse_line(char *line)
exception(-1, _("Invalid binary operator"));
}
}
- while (get_pri(get_last_op()) >= get_pri(buffer[0]) && (((get_last_op() & 127) != '(') && ((get_last_op() & 127) != '['))) {
+ 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]);
+ 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));
}
- break;
+ 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"));
@@ -209,15 +242,16 @@ void parse_line(char *line)
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));
- }
+ 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"));
@@ -228,28 +262,30 @@ void parse_line(char *line)
exception(-1, _("Parse error: enclosure mismatch"));
act_pile(get_func(op));
}
- 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] >= '0') && (buffer[0] <= '9')) || (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();
+ if (!get_last_call())
+ increment_call();
} else if (buffer[0]) {
exception(-1, _("Invalid character"));
}
+ popcontext();
}
+
+ popcontext();
}
#ifndef HAVE_CONFIG_H
-void exception(int level, char *msg)
-{
- fprintf(stderr, "%s\n", msg);
- exit(level);
-}
+/* Les quelques fonctions de test, lorsque le parser est compilé en dehors du projet. */
void push_pile(char *word)
{
@@ -279,9 +315,9 @@ void act_pile(int func)
case OP_MOINS_UNARY:
op = '|';
break;
- case OP_FUNC_CALL:
- op = '@';
- break;
+ case OP_FUNC_CALL:
+ op = '@';
+ break;
case OP_DECAL:
op = '[';
break;
@@ -295,15 +331,20 @@ void act_pile(int func)
void main(void)
{
parse_line("ADD R18, R20, 39;");
- printf("\n\n"); fflush(stdout);
+ printf("\n\n");
+ fflush(stdout);
parse_line("MOV R31, Bidule[48 + R12];");
- printf("\n\n"); fflush(stdout);
+ printf("\n\n");
+ fflush(stdout);
parse_line("MOV R12, [R3];");
- printf("\n\n"); fflush(stdout);
+ printf("\n\n");
+ fflush(stdout);
parse_line("MOV R22, Truc[(3+2)*8];");
- printf("\n\n"); fflush(stdout);
+ 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);
+ printf("\n\n");
+ fflush(stdout);
}
#endif