Kajetan Johannes Hammerle 3 éve
szülő
commit
dc59a725ad
3 módosított fájl, 113 hozzáadás és 36 törlés
  1. 9 1
      tests/pre/pre
  2. 5 0
      tests/pre/pre.out
  3. 99 35
      tokenizer/File.c

+ 9 - 1
tests/pre/pre

@@ -1,8 +1,16 @@
 #define WUSI print 5;
 #define BAUM print 6;
+#define GUSI WUSI WUSI
 #define IF if(true) {
 
+#start HUSI
+    print 1;
+    print 2;
+#end
+
 void main() {
-    WUSI WUSI BAUM WUSI
+    WUSI GUSI BAUM WUSI
     IF BAUM }
+    HUSI 
+    HUSI
 }

+ 5 - 0
tests/pre/pre.out

@@ -1,5 +1,10 @@
 5
 5
+5
 6
 5
 6
+1
+2
+1
+2

+ 99 - 35
tokenizer/File.c

@@ -88,7 +88,7 @@ static void fReadCommandString(OpenFile* of, char* buffer, int size) {
             files.error("unknown too long command");
         } else if(isLetter(c)) {
             buffer[index++] = c;
-        } else if(c == ' ') {
+        } else if(c == ' ' || c == '\n') {
             break;
         } else {
             files.error("unexpected character '%c'", (char)c);
@@ -98,7 +98,11 @@ static void fReadCommandString(OpenFile* of, char* buffer, int size) {
     buffer[index] = '\0';
 }
 
-static void fDefine(OpenFile* of) {
+static const char* fGetDefineName(Define* d) {
+    return files.files[d->name.fileIndex].content + d->name.index;
+}
+
+static int fStartDefine(OpenFile* of) {
     if(files.defineIndex >= MAX_INDEX) {
         files.error("too many defines");
     }
@@ -113,18 +117,61 @@ static void fDefine(OpenFile* of) {
     d->name.index = of->index;
     fAdd(of, command, strlen(command) + 1);
 
+    for(int i = 0; i < files.defineIndex - 1; i++) {
+        if(strcmp(command, fGetDefineName(files.defines + i)) == 0) {
+            files.error("'%s' is already defined", command);
+        }
+    }
+
     d->code.fileIndex = of->arrayIndex;
     d->code.index = of->index;
+    return end;
+}
+
+static void fFinishDefine(OpenFile* of, int end, int newLines) {
+    fAddChar(of, '\0');
+    fSetInt(of, end, of->index);
+    for(int i = 0; i < newLines; i++) {
+        fAddChar(of, '\n');
+    }
+}
+
+static void fDefine(OpenFile* of) {
+    int end = fStartDefine(of);
     while(true) {
         int c = fGet(of);
-        if(c == EOF || c == '\n') {
+        if(c == '#') {
+            files.error("# inside define");
+        } else if(c == EOF || c == '\n') {
             break;
         }
         fAddChar(of, c);
     }
-    fAddChar(of, '\0');
-    fSetInt(of, end, of->index);
-    fAddChar(of, '\n');
+    fFinishDefine(of, end, 1);
+}
+
+static void fStart(OpenFile* of) {
+    int end = fStartDefine(of);
+    int newLines = 2;
+    while(true) {
+        int c = fGet(of);
+        if(c == '#') {
+            char end[64];
+            fReadCommandString(of, end, 64);
+            if(strcmp(end, "end") == 0) {
+                break;
+            }
+            files.error("invalid command '%s' inside define region", end);
+        } else if(c == EOF) {
+            files.error("unclosed #start");
+        }
+        if(c == '\n') {
+            newLines++;
+            c = ' ';
+        }
+        fAddChar(of, c);
+    }
+    fFinishDefine(of, end, newLines);
 }
 
 static void fReadCommand(OpenFile* of) {
@@ -132,6 +179,8 @@ static void fReadCommand(OpenFile* of) {
     fReadCommandString(of, command, 64);
     if(strcmp(command, "define") == 0) {
         fDefine(of);
+    } else if(strcmp(command, "start") == 0) {
+        fStart(of);
     } else {
         files.error("invalid command '%s'", command);
     }
@@ -177,7 +226,9 @@ void fOpen(const char* path, FileError fe) {
 
 void fClose() {
     for(int i = 0; i < files.fileIndex; i++) {
-        fclose(files.files[i].file);
+        if(files.files[i].file != NULL) {
+            fclose(files.files[i].file);
+        }
         free(files.files[i].content);
     }
 }
@@ -190,10 +241,6 @@ static int fReadChar() {
     return currentFile()->content[files.readIndex.index];
 }
 
-static const char* fGetDefineName(Define* d) {
-    return files.files[d->name.fileIndex].content + d->name.index;
-}
-
 static bool fCompare(const char* a, const char* b, unsigned int bLength) {
     return strncmp(a, b, bLength) == 0 && strlen(a) == bLength;
 }
@@ -206,42 +253,59 @@ static void fEnter(Define* d) {
     files.readIndex = d->code;
 }
 
-static void fPrepareChar() {
-    int c = fReadChar();
-    if(c == '\0') {
-        if(stackIndex <= 0) {
-            files.error("define stack underflow");
-        }
-        files.readIndex = stack[--stackIndex];
+static bool fCheckForReplacement() {
+    OpenFile* of = currentFile();
+    int start = files.readIndex.index;
+    int index = start;
+    while(index < of->index && isLetter(of->content[index])) {
+        index++;
     }
-    if(c == '#') {
-        int end = fReadInt(currentFile(), files.readIndex.index + 1);
-        files.readIndex.index = end;
-    }
-    if(isLetter(c) && !isLetter(lastChar)) {
-        OpenFile* of = currentFile();
-        int start = files.readIndex.index;
-        int index = start;
-        while(index < of->index && isLetter(of->content[index])) {
-            index++;
+    for(int i = 0; i < files.defineIndex; i++) {
+        Define* d = files.defines + i;
+        const char* name = fGetDefineName(d);
+        if(fCompare(name, of->content + start, index - start)) {
+            files.readIndex.index = index;
+            fEnter(d);
+            return true;
         }
-        for(int i = 0; i < files.defineIndex; i++) {
-            Define* d = files.defines + i;
-            const char* name = fGetDefineName(d);
-            if(fCompare(name, of->content + start, index - start)) {
-                files.readIndex.index = index;
-                fEnter(d);
+    }
+    return false;
+}
+
+static void fPrepareChar() {
+    while(true) {
+        int c = fReadChar();
+        if(c == '\0') {
+            if(stackIndex <= 0) {
+                files.error("define stack underflow");
             }
+            files.readIndex = stack[--stackIndex];
+        } else if(c == '#') {
+            files.readIndex.index =
+                fReadInt(currentFile(), files.readIndex.index + 1);
+        } else if(isLetter(c) && !isLetter(lastChar)) {
+            if(fCheckForReplacement()) {
+                continue;
+            }
+            break;
+        } else {
+            break;
         }
     }
 }
 
-int fRead() {
+static int fReadI() {
     fPrepareChar();
     lastChar = fReadChar();
     return currentFile()->content[files.readIndex.index++];
 }
 
+int fRead() {
+    int i = fReadI();
+    putchar(i);
+    return i;
+}
+
 int fPeek() {
     fPrepareChar();
     return fReadChar();