Преглед на файлове

LibRegex: Support ECMA-262 Unicode escapes of the form "\u{code_point}"

When the Unicode flag is set, regular expressions may escape code points
by surrounding the hexadecimal code point with curly braces, e.g. \u{41}
is the character "A".

When the Unicode flag is not set, this should be considered a repetition
symbol - \u{41} is the character "u" repeated 41 times. This is left as
a TODO for now.
Timothy Flynn преди 4 години
родител
ревизия
345ef6abba
променени са 2 файла, в които са добавени 27 реда и са изтрити 0 реда
  1. 6 0
      Tests/LibRegex/Regex.cpp
  2. 21 0
      Userland/Libraries/LibRegex/RegexParser.cpp

+ 6 - 0
Tests/LibRegex/Regex.cpp

@@ -510,6 +510,11 @@ TEST_CASE(ECMA262_parse)
         { "\\uxxxx", regex::Error::InvalidPattern, ECMAScriptFlags::Unicode },
         { "\\ud83d", regex::Error::NoError, ECMAScriptFlags::Unicode },
         { "\\ud83d\\uxxxx", regex::Error::InvalidPattern, ECMAScriptFlags::Unicode },
+        { "\\u{0}", regex::Error::NoError, ECMAScriptFlags::Unicode },
+        { "\\u{10ffff}", regex::Error::NoError, ECMAScriptFlags::Unicode },
+        { "\\u{10ffff", regex::Error::InvalidPattern, ECMAScriptFlags::Unicode },
+        { "\\u{10ffffx", regex::Error::InvalidPattern, ECMAScriptFlags::Unicode },
+        { "\\u{110000}", regex::Error::InvalidPattern, ECMAScriptFlags::Unicode },
     };
 
     for (auto& test : tests) {
@@ -605,6 +610,7 @@ TEST_CASE(ECMA262_unicode_match)
         { "\\ude00", "😀", false, ECMAScriptFlags::Unicode },
         { "\\ud83d\\ude00", "😀", true },
         { "\\ud83d\\ude00", "😀", true, ECMAScriptFlags::Unicode },
+        { "\\u{1f600}", "😀", true, ECMAScriptFlags::Unicode },
         { "\\ud83d\\ud83d", "\xed\xa0\xbd\xed\xa0\xbd", true },
         { "\\ud83d\\ud83d", "\xed\xa0\xbd\xed\xa0\xbd", true, ECMAScriptFlags::Unicode },
     };

+ 21 - 0
Userland/Libraries/LibRegex/RegexParser.cpp

@@ -7,6 +7,7 @@
 
 #include "RegexParser.h"
 #include "RegexDebug.h"
+#include <AK/CharacterTypes.h>
 #include <AK/String.h>
 #include <AK/StringBuilder.h>
 #include <AK/StringUtils.h>
@@ -1440,6 +1441,26 @@ bool ECMA262Parser::parse_atom_escape(ByteCode& stack, size_t& match_length_mini
     }
 
     if (try_skip("u")) {
+        if (match(TokenType::LeftCurly)) {
+            consume();
+
+            if (!unicode) {
+                // FIXME: In non-Unicode mode, this should be parsed as a repetition symbol (repeating the 'u').
+                TODO();
+            }
+
+            auto code_point = read_digits(ReadDigitsInitialZeroState::Allow, true, 6);
+            if (code_point.has_value() && is_unicode(*code_point) && match(TokenType::RightCurly)) {
+                consume();
+                match_length_minimum += 1;
+                stack.insert_bytecode_compare_values({ { CharacterCompareType::Char, (ByteCodeValueType)code_point.value() } });
+                return true;
+            }
+
+            set_error(Error::InvalidPattern);
+            return false;
+        }
+
         if (auto code_point = read_digits(ReadDigitsInitialZeroState::Allow, true, 4); code_point.has_value()) {
             // In Unicode mode, we need to combine surrogate pairs into a single code point. But we also need to be
             // rather forgiving if the surrogate pairs are invalid. So if a second code unit follows this code unit,