Coding style fixlet.
[TP_AL_C.git] / lexer / main.c
index 691d54eef5162acaa4f8c5ee5514e0f02d1834bb..f2b6df47660f77bb7c43c49b4752a7ea52582966 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <stdbool.h>
-#include <wchar.h>
+#include <getopt.h>
 
-#define TOKEN_MAX 500
+#include "global_vars.h"
+#include "lexical_analyzer.h"
+#include "syntactic_analyzer.h"
+#include "print_helper.h"
 
-struct token_s {
-    const char* type;
-    wint_t value[50];
-};
-
-struct token_s token[TOKEN_MAX] = {NULL, 0};
-
-FILE *source = NULL, *target = NULL;
-wint_t c;
-unsigned int tokenFound = 0;
-enum TokenType {
-    MOTCLE,
-    SECTION,
-    SSECTION,
-    NPARA,
-    MOT,
-    FIN
-} tokenType;
-const char* tokenTypestr[] = { "MOTCLE", "SECTION", "SSECTION", "NPARA", "MOT", "FIN" };
-
-/* It looks silly to check for each characters but for debugging, it's just the way to go */
-bool istAlpha() {
-    if (c == L'a' || c == L'b' || c == L'c' || c == L'd' || c == L'e' || c == L'f' || c == L'g' || \
-        c == L'h' || c == L'i' || c == L'j' || c == L'k' || c == L'l' || c == L'm' || c == L'n' || \
-        c == L'o' || c == L'p' || c == L'q' || c == L'r' || c == L's' || c == L't' || c == L'u' || \
-        c == L'v' || c == L'w' || c == L'x' || c == L'y' || c == L'z' || \
-        c == L'A' || c == L'B' || c == L'C' || c == L'D' || c == L'E' || c == L'F' || c == L'G' || \
-        c == L'H' || c == L'I' || c == L'J' || c == L'K' || c == L'L' || c == L'M' || c == L'N' || \
-        c == L'O' || c == L'P' || c == L'Q' || c == L'R' || c == L'S' || c == L'T' || c == L'U' || \
-        c == L'V' || c == L'W' || c == L'X' || c == L'Y' || c == L'Z' || \
-        c == L'.' || c == L'?' || c == L'!' || c == L',' || c == L';' || c == L':' || c == L'-' || \
-        c == L'\''|| c == L'#' || \
-        c == L'0' || c == L'1' || c == L'2' || c == L'3' || c == L'4' || c == L'5' || c == L'6' || \
-        c == L'7' || c == L'8' || c == L'9' || \
-        c == L'à' || c == L'â' || c == L'ç' || c == L'è' || c == L'é' || c == L'î' || c == L'ô' || \
-        c == L'ù' || c == L'û' || \
-        c == L'À' || c == L'Â' || c == L'Ç' || c == L'È' || c == L'É' || c == L'Î' || c == L'Ô' || \
-        c == L'Ù' || c == L'Û') {
-            return true;
-        }
-        return false;
+void do_lexical_analysis() {
+    c = fgetwc(source); // lecture du premier caractere
+    do {
+        scanner();
+        wprint_token_target();
+        token[tokenFound].type = tokenTypestr[tokenType];
+        tokenFound++;
+    } while (tokenType != FIN); // tant que la fin du fichier n'est pas atteinte
 }
 
-bool isSeparator() {
-    if (c == L'\t' || c == L' ' || c == L'\n') {
-        return true;
-    }
-    return false;
+void do_syntactic_analysis() {
+    fputws(L"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"fr_FR\" lang=\"fr_FR\">\n",
+           target);
+    c = fgetwc(source); // lecture du premier caractere
+    analyze_AXIOME();
+    fputws(L"</html>\n", target);
 }
 
-int scanner() {
-    unsigned int i = 0;
-    wchar_t m[6];
-
-init:
-    if (c == L' ' || c == L'\t') {
-        c = fgetwc(source);
-        goto init;
-    }
-    if (c == L'\n') {
-        c = fgetwc(source);
-        goto initLV1;
-    }
-    if (c == L'>') {
-        c = fgetwc(source);
-        goto MC1;
-    }
-    if (c == L'=') {
-        c = fgetwc(source);
-        goto S1SS1;
-    }
-    if (istAlpha()) {
-        token[tokenFound].value[i] = c;
-        i++;
-        c = fgetwc(source);
-        goto M1;
-    }
-    if (c == WEOF) {
-        goto FIN;
-    }
-    goto error;
-
-MC1:
-    if (c == L'A' && !wcscmp(fgetws(m, 6, source), L"uteur")) {
-        wcscpy((wchar_t*)token[tokenFound].value, L">Auteur");
-        c = fgetwc(source);
-        goto MC2;
-    }
-    if (c == L'T' && !wcscmp(fgetws(m, 5, source), L"itre")) {
-        wcscpy((wchar_t*)token[tokenFound].value, L">Titre");
-        c = fgetwc(source);
-        goto MC2;
-    }
-    goto error;
-
-S1SS1:
-    if (c == L'=') {
-        c = fgetwc(source);
-        goto SS2;
-    }
-    if (isSeparator() || c == WEOF) {
-        goto SECTION;
-    }
-    goto error;
-
-SS2:
-    if (isSeparator() || c == WEOF) {
-        goto SSECTION;
-    }
-    goto error;
-
-SECTION:
-    tokenType = SECTION;
-    return EXIT_SUCCESS;
-
-SSECTION:
-    tokenType = SSECTION;
-    return EXIT_SUCCESS;
-
-M1:
-    if (istAlpha()) {
-        token[tokenFound].value[i] = c;
-        i++;
-        c = fgetwc(source);
-        goto M1;
-    }
-    if (isSeparator() || c == WEOF) {
-        goto MOT;
-    }
-    goto error;
-
-initLV1:
-    if (c == L' ' || c == L'\t') {
-        c = fgetwc(source);
-        goto initLV1;
-    }
-    if (c == L'\n') {
-        c = fgetwc(source);
-        goto initLV1LV2;
-    }
-    if (istAlpha()) {
-        token[tokenFound].value[i] = c;
-        i++;
-        c = fgetwc(source);
-        goto M1;
-    }
-    if (c == L'=') {
-        c = fgetwc(source);
-        goto S1SS1;
-    }
-    if (c == L'>') {
-        c = fgetwc(source);
-        goto MC1;
-    }
-    if (c == WEOF) {
-        goto FIN;
-    }
-    goto error;
+void print_usage(const char* name) {
+    fprintf(stdout,"Usage: %s [options]\n"
+                   "Where [options] are:\n"
+                   " -h, --help: display this help message\n"
+                   " -l, --lexical-only: do only the lexical analysis\n"
+                   " -i, --input<filename>: use <filename> as input file instead of standard input\n"
+                   " -o, --output<filename>: use <filename> as output file instead of standard output\n",
+            name);
+    fflush(stdout);
+}
 
-initLV1LV2:
-    if (isSeparator()) {
-        c = fgetwc(source);
-        goto initLV1LV2;
-    }
-    if (istAlpha()) {
-        goto NPARA;
-    }
-    if (c == L'>') {
-        c = fgetwc(source);
-        goto MC1;
-    }
-    if (c == L'=') {
-        c = fgetwc(source);
-        goto S1SS1;
-    }
-    if (c == WEOF) {
-        goto FIN;
+int main(int argc, char **argv) {
+    /* In and out files name */
+    const char* in_file = NULL;
+    const char* out_file = NULL;
+    static int hflag = 0;
+    static int lflag = 0;
+
+    /* getopt_long stores the option index here. */
+    int option_index = 0;
+
+    static struct option long_options[] =
+    {
+        {"help", no_argument, &hflag, 1},
+        {"input", optional_argument, NULL, 'i'},
+        {"lexical-only", no_argument, &lflag, 1},
+        {"output", optional_argument, NULL, 'o'},
+        {0, 0, 0, 0}
+    };
+
+    int c_in;
+
+    while ((c_in = getopt_long(argc, argv, "hi::lo::", long_options,
+                               &option_index)) != -1) {
+        switch (c_in) {
+            case 'h':
+                hflag = 1;
+                break;
+            case 'i':
+                if (optarg != NULL) {
+                    in_file = optarg;
+                }
+                break;
+            case 'l':
+                lflag = 1;
+                break;
+            case 'o':
+                if (optarg != NULL) {
+                    out_file = optarg;
+                }
+                break;
+            case 0:
+                /* getopt_long() set a variable, just keep going */
+                break;
+            case ':':
+                /* missing option argument */
+                pr_error("%s: option '-%c' requires an argument\n",
+                         argv[0], optopt);
+                break;
+            case '?':
+            default:
+                /* invalid option */
+                pr_error("%s: option '-%c' is invalid: ignored\n",
+                         argv[0], optopt);
+                /* print the help message for invalid options */
+                hflag = 1;
+                break;
+        }
     }
-    goto error;
-
-NPARA:
-    tokenType = NPARA;
-    return EXIT_SUCCESS;
-
-MOT:
-    tokenType = MOT;
-    return EXIT_SUCCESS;
 
-MC2:
-    if (isSeparator() || c == WEOF) {
-        goto MOTCLE;
+    if (in_file != NULL) {
+        // Ouvre le fichier source en lecture seulement (le fichier doit exister) :
+        source = fopen(in_file, "r+");
+        if (source == NULL) {
+            pr_error("Fail to open file %s\n", in_file);
+            return EXIT_FAILURE;
+        }
+    } else {
+        source = stdin;
     }
-    goto error;
 
-MOTCLE:
-    tokenType = MOTCLE;
-    return EXIT_SUCCESS;
-
-FIN:
-    tokenType = FIN;
-    return EXIT_SUCCESS;
-
-error:
-    tokenType = FIN;
-    return EXIT_FAILURE;
-}
-
-int main() {
-    // Ouvre le fichier test.txt en lecture seulement (le fichier doit exister) :
-    source = fopen("test.txt", "r+");
-    // Cree et ouvre un fichier target.html en lecture/ecriture
-    // avec suppression du contenu au prealable :
-    target = fopen("target.html", "w+");
-
-    if (source == NULL) {
-        printf("Impossible d'ouvrir le fichier source\n");
-        return -1;
+    if (out_file != NULL) {
+        // Cree et ouvre le fichier cible en lecture/ecriture
+        // avec suppression du contenu au prealable :
+        target = fopen(out_file, "w+");
+        if (target == NULL) {
+            pr_error("Fail to open file %s\n", out_file);
+            return EXIT_FAILURE;
+        }
+    } else {
+        target = stdout;
     }
 
-    if (target == NULL) {
-        printf("Impossible d'ouvrir le fichier target\n");
-        return -1;
+    if (hflag) {
+        print_usage(argv[0]);
+    } else if (lflag) {
+        do_lexical_analysis();
+    } else {
+        do_syntactic_analysis();
     }
 
-    c = fgetwc(source); // lecture du premier caractere
-    do {
-        int scanrt = scanner();
-        if (scanrt == EXIT_FAILURE) {
-            wprintf(L"Scanner error with token value: %ls\n", token[tokenFound].value);
-            exit(EXIT_FAILURE);
-        }
-        if (c != WEOF) {
-            wprintf(L"%20s: %ls\n", tokenTypestr[tokenType], token[tokenFound].value);
-        } else {
-            wprintf(L"%20s\n", tokenTypestr[tokenType]);
-        }
-        token[tokenFound].type = tokenTypestr[tokenType];
-        tokenFound++;
-    } while (tokenType != FIN); // tant que la fin du fichier n'est pas atteinte
-
     if (source != NULL) fclose(source); // fermeture du fichier source
     if (target != NULL) fclose(target); // fermeture du fichier target