Quellcode durchsuchen

constant strings

Kajetan Johannes Hammerle vor 3 Jahren
Ursprung
Commit
c17deec7cf
10 geänderte Dateien mit 81 neuen und 7 gelöschten Zeilen
  1. 15 1
      Compiler.c
  2. 1 0
      Object.c
  3. 2 1
      Object.h
  4. 1 0
      Operation.h
  5. 21 0
      Script.c
  6. 1 0
      Test.c
  7. 32 4
      Tokenizer.c
  8. 2 1
      Tokenizer.h
  9. 3 0
      tests/strings/const_string
  10. 3 0
      tests/strings/const_string.out

+ 15 - 1
Compiler.c

@@ -1,6 +1,7 @@
 #include <setjmp.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "Compiler.h"
 #include "FunctionMap.h"
@@ -129,8 +130,20 @@ static void cConstantFloat() {
     cAddFloat(value);
 }
 
+static void cConstantString() {
+    int length;
+    const char* s = tReadString(&length);
+    if(s == NULL) {
+        cError("text without string on line %d", line);
+    }
+    cAddOperation(OP_PUSH_CONST_STRING);
+    cAddInt(length);
+    bcAddBytes(code, s, length);
+}
+
 static const char* cReadString() {
-    const char* literal = tReadString();
+    int length;
+    const char* literal = tReadString(&length);
     if(literal == NULL) {
         cError("literal without string on line %d", line);
     }
@@ -206,6 +219,7 @@ static void cPrimary() {
     switch(t) {
         case T_INT: cConstantInt(); break;
         case T_FLOAT: cConstantFloat(); break;
+        case T_TEXT: cConstantString(); break;
         case T_NULL: cAddOperation(OP_PUSH_NULL); break;
         case T_TRUE: cAddOperation(OP_PUSH_TRUE); break;
         case T_FALSE: cAddOperation(OP_PUSH_FALSE); break;

+ 1 - 0
Object.c

@@ -4,6 +4,7 @@ const char* oGetName(ObjectType ot) {
     switch(ot) {
         case OT_INT: return "int";
         case OT_FLOAT: return "float";
+        case OT_CONST_STRING: return "const string";
         case OT_NULL: return "null";
         case OT_BOOL: return "bool";
         case OT_VOID: return "void";

+ 2 - 1
Object.h

@@ -1,13 +1,14 @@
 #ifndef OBJECT_H
 #define OBJECT_H
 
-typedef enum ObjectType { OT_INT, OT_FLOAT, OT_NULL, OT_BOOL, OT_VOID } ObjectType;
+typedef enum ObjectType { OT_INT, OT_FLOAT, OT_CONST_STRING, OT_NULL, OT_BOOL, OT_VOID } ObjectType;
 
 typedef struct Object {
     ObjectType type;
     union Data {
         int intValue;
         float floatValue;
+        const char* stringValue;
     } data;
 } Object;
 

+ 1 - 0
Operation.h

@@ -5,6 +5,7 @@ typedef enum Operation {
     OP_NOTHING,
     OP_PUSH_INT,
     OP_PUSH_FLOAT,
+    OP_PUSH_CONST_STRING,
     OP_PUSH_NULL,
     OP_PUSH_TRUE,
     OP_PUSH_FALSE,

+ 21 - 0
Script.c

@@ -18,6 +18,7 @@ static bool sPrinter(Object* o) {
     switch(o->type) {
         case OT_INT: printf("%d\n", o->data.intValue); return false;
         case OT_FLOAT: printf("%.2f\n", o->data.floatValue); return false;
+        case OT_CONST_STRING: printf("%s\n", o->data.stringValue); return false;
         case OT_NULL: printf("null\n"); return false;
         case OT_BOOL: printf(o->data.intValue ? "true\n" : "false\n"); return false;
         case OT_VOID: printf("void\n"); return false;
@@ -228,6 +229,16 @@ static void sPushCodeFloat(Script* sc) {
     sPushFloat(sc, value);
 }
 
+static void sPushCodeString(Script* sc) {
+    int value = 0;
+    if(sReadInt(sc, &value)) {
+        char* s = (char*)(sc->code->code + sc->readIndex);
+        sc->readIndex += value;
+        Object o = {.type = OT_CONST_STRING, .data.stringValue = s};
+        sPush(sc, &o);
+    }
+}
+
 static void sNumberBinary(Script* sc, int (*fInt)(Script*, int, int), float (*fFloat)(float, float)) {
     Object o[2];
     if(sPop(sc, o) || sPop(sc, o + 1)) {
@@ -488,6 +499,7 @@ static void sConsumeInstruction(Script* sc) {
         case OP_NOTHING: break;
         case OP_PUSH_INT: sPushCodeInt(sc); break;
         case OP_PUSH_FLOAT: sPushCodeFloat(sc); break;
+        case OP_PUSH_CONST_STRING: sPushCodeString(sc); break;
         case OP_PUSH_NULL: sPushNull(sc); break;
         case OP_PUSH_TRUE: sPushBool(sc, true); break;
         case OP_PUSH_FALSE: sPushBool(sc, false); break;
@@ -590,6 +602,14 @@ static void sPrintFloat(Script* sc, const char* msg) {
     printf("%s %.2f\n", msg, value);
 }
 
+static void sPrintString(Script* sc, const char* msg) {
+    int length = 0;
+    sReadInt(sc, &length);
+    char* s = (char*)(sc->code->code + sc->readIndex);
+    sc->readIndex += length;
+    printf("%s %d \"%s\"\n", msg, length, s);
+}
+
 void sPrintCode(Script* sc) {
     int oldRead = sc->readIndex;
     sc->readIndex = 0;
@@ -599,6 +619,7 @@ void sPrintCode(Script* sc) {
             case OP_NOTHING: puts("Nothing"); break;
             case OP_PUSH_INT: sPrintInt(sc, "Push Int"); break;
             case OP_PUSH_FLOAT: sPrintFloat(sc, "Push Float"); break;
+            case OP_PUSH_CONST_STRING: sPrintString(sc, "Push Const String"); break;
             case OP_PUSH_NULL: puts("Push null"); break;
             case OP_PUSH_TRUE: puts("Push true"); break;
             case OP_PUSH_FALSE: puts("Push false"); break;

+ 1 - 0
Test.c

@@ -37,6 +37,7 @@ static bool tsPrinter(Object* o) {
     switch(o->type) {
         case OT_INT: tsPrintToBuffer("%d\n", o->data.intValue); return false;
         case OT_FLOAT: tsPrintToBuffer("%.2f\n", o->data.floatValue); return false;
+        case OT_CONST_STRING: tsPrintToBuffer("%s\n", o->data.stringValue); return false;
         case OT_NULL: tsPrintToBuffer("null\n"); return false;
         case OT_BOOL: tsPrintToBuffer(o->data.intValue ? "true\n" : "false\n"); return false;
         case OT_VOID: tsPrintToBuffer("void\n"); return false;

+ 32 - 4
Tokenizer.c

@@ -134,6 +134,32 @@ static bool tParseNumber(int c) {
     }
 }
 
+static bool tAddString() {
+    if(!tAddToken(T_TEXT)) {
+        return false;
+    }
+    while(true) {
+        int c = tRead();
+        if(c == '"') {
+            break;
+        } else if(c == '\\') {
+            switch(tRead()) {
+                case '"': c = '"'; break;
+                case '\\': c = '\\'; break;
+                default: tError("unknown escaped character at line %d", line); return false;
+            }
+        } else if(c == EOF) {
+            tError("unclosed string starting at line %d", line);
+            return false;
+        }
+        if(!tAdd(&c, 1)) {
+            return false;
+        }
+    }
+    char c = '\0';
+    return tAdd(&c, 1);
+}
+
 static bool tAddTokenChecked(int c, Token tc, Token te, Token t) {
     if(tReadIf(c)) {
         return tAddToken(tc);
@@ -187,6 +213,7 @@ static bool tParseToken() {
         case ')': return tAddToken(T_CLOSE_BRACKET);
         case '{': return tAddToken(T_OPEN_CURVED_BRACKET);
         case '}': return tAddToken(T_CLOSE_CURVED_BRACKET);
+        case '"': return tAddString();
     }
     tError("unknown character on line %d: %c", line, c);
     return false;
@@ -255,14 +282,14 @@ bool tReadFloat(float* f) {
     return false;
 }
 
-const char* tReadString() {
+const char* tReadString(int* length) {
+    *length = 0;
     const char* s = tokenBuffer + readIndex;
     while(readIndex <= writeIndex) {
-        if(tokenBuffer[readIndex] == '\0') {
-            readIndex++;
+        (*length)++;
+        if(tokenBuffer[readIndex++] == '\0') {
             return s;
         }
-        readIndex++;
     }
     return NULL;
 }
@@ -271,6 +298,7 @@ const char* tGetTokenName(Token token) {
     switch(token) {
         case T_INT: return "int";
         case T_FLOAT: return "float";
+        case T_TEXT: return "text";
         case T_NULL: return "null";
         case T_TRUE: return "true";
         case T_FALSE: return "false";

+ 2 - 1
Tokenizer.h

@@ -7,6 +7,7 @@
 typedef enum Token {
     T_INT,
     T_FLOAT,
+    T_TEXT,
     T_NULL,
     T_TRUE,
     T_FALSE,
@@ -73,7 +74,7 @@ Token tReadToken();
 bool tReadInt(int* i);
 bool tReadInt16(int16* i);
 bool tReadFloat(float* f);
-const char* tReadString();
+const char* tReadString(int* length);
 
 int tGetMarker();
 void tResetToMarker(int marker);

+ 3 - 0
tests/strings/const_string

@@ -0,0 +1,3 @@
+print "Hello World";
+print "umlaut üöäÜÖÄ";
+print "escaping: \"\\";

+ 3 - 0
tests/strings/const_string.out

@@ -0,0 +1,3 @@
+Hello World
+umlaut üöäÜÖÄ
+escaping: "\