blueloveTH 3 лет назад
Родитель
Сommit
a942b90f78
3 измененных файлов с 61 добавлено и 4 удалено
  1. 34 3
      src/compiler.h
  2. 9 0
      src/parser.h
  3. 18 1
      tests/_rawstring.py

+ 34 - 3
src/compiler.h

@@ -115,11 +115,43 @@ public:
     }
 
     _Str eatStringUntil(char quote, bool raw) {
+        bool quote3 = false;
+        std::string_view sv = parser->lookahead(2);
+        if(sv.size() == 2 && sv[0] == quote && sv[1] == quote) {
+            quote3 = true;
+            parser->eatChar();
+            parser->eatChar();
+        }
+
         std::vector<char> buff;
         while (true) {
             char c = parser->eatCharIncludeNewLine();
-            if (c == quote) break;
-            if (c == '\0' || c == '\n') syntaxError("EOL while scanning string literal");
+            if (c == quote){
+                if(quote3){
+                    sv = parser->lookahead(2);
+                    if(sv.size() == 2 && sv[0] == quote && sv[1] == quote) {
+                        parser->eatChar();
+                        parser->eatChar();
+                        break;
+                    }
+                    buff.push_back(c);
+                } else {
+                    break;
+                }
+            }
+            if (c == '\0'){
+                if(quote3 && parser->src->mode == SINGLE_MODE){
+                    throw NeedMoreLines(false);
+                }
+                syntaxError("EOL while scanning string literal");
+            }
+            if (c == '\n'){
+                if(!quote3) syntaxError("EOL while scanning string literal");
+                else{
+                    buff.push_back(c);
+                    continue;
+                }
+            }
             if (!raw && c == '\\') {
                 switch (parser->eatCharIncludeNewLine()) {
                     case '"':  buff.push_back('"');  break;
@@ -128,7 +160,6 @@ public:
                     case 'n':  buff.push_back('\n'); break;
                     case 'r':  buff.push_back('\r'); break;
                     case 't':  buff.push_back('\t'); break;
-                    case '\n': case '\r': break;
                     default: syntaxError("invalid escape character");
                 }
             } else {

+ 9 - 0
src/parser.h

@@ -124,6 +124,15 @@ struct Parser {
         return *current_char;
     }
 
+    std::string_view lookahead(int n){
+        const char* c = current_char;
+        for(int i=0; i<n; i++){
+            if(*c == '\0') return std::string_view(current_char, i);
+            c++;
+        }
+        return std::string_view(current_char, n);
+    }
+
     char peekNextChar() {
         if (peekChar() == '\0') return '\0';
         return *(current_char + 1);

+ 18 - 1
tests/_rawstring.py

@@ -4,4 +4,21 @@ assert a == '1\\232\\\\\\13'
 
 b = r'测\试'
 assert len(b) == 3
-assert b == '测\\试'
+assert b == '测\\试'
+
+s = '''asdasd
+asds1321321321测试测试
+'''
+
+assert s == 'asdasd\nasds1321321321测试测试\n'
+
+s = r'''asdasd
+asds1321321321测试\测试'''
+
+assert s == 'asdasd\nasds1321321321测试\\测试'
+
+s = f'''->->{s}<-<-
+{123}
+'''
+
+assert s == '->->asdasd\nasds1321321321测试\\测试<-<-\n123\n'