From d25e11bee6ca5ca523884da132d18e1400e077b9 Mon Sep 17 00:00:00 2001
From: Minteck <nekostarfan@gmail.com>
Date: Tue, 24 Aug 2021 14:41:48 +0200
Subject: Initial commit

---
 node_modules/meriyah/src/lexer/regexp.ts | 143 +++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100644 node_modules/meriyah/src/lexer/regexp.ts

(limited to 'node_modules/meriyah/src/lexer/regexp.ts')

diff --git a/node_modules/meriyah/src/lexer/regexp.ts b/node_modules/meriyah/src/lexer/regexp.ts
new file mode 100644
index 0000000..4a48d50
--- /dev/null
+++ b/node_modules/meriyah/src/lexer/regexp.ts
@@ -0,0 +1,143 @@
+import { Chars } from '../chars';
+import { Context, ParserState } from '../common';
+import { Token } from '../token';
+import { advanceChar } from './common';
+import { isIdentifierPart } from './charClassifier';
+import { report, Errors } from '../errors';
+
+/**
+ * Scans regular expression
+ *
+ * @param parser Parser object
+ * @param context Context masks
+ */
+
+export function scanRegularExpression(parser: ParserState, context: Context): Token {
+  const enum RegexState {
+    Empty = 0,
+    Escape = 0x1,
+    Class = 0x2
+  }
+  const bodyStart = parser.index;
+  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
+  let preparseState = RegexState.Empty;
+
+  loop: while (true) {
+    const ch = parser.currentChar;
+    advanceChar(parser);
+
+    if (preparseState & RegexState.Escape) {
+      preparseState &= ~RegexState.Escape;
+    } else {
+      switch (ch) {
+        case Chars.Slash:
+          if (!preparseState) break loop;
+          else break;
+        case Chars.Backslash:
+          preparseState |= RegexState.Escape;
+          break;
+        case Chars.LeftBracket:
+          preparseState |= RegexState.Class;
+          break;
+        case Chars.RightBracket:
+          preparseState &= RegexState.Escape;
+          break;
+        case Chars.CarriageReturn:
+        case Chars.LineFeed:
+        case Chars.LineSeparator:
+        case Chars.ParagraphSeparator:
+          report(parser, Errors.UnterminatedRegExp);
+        default: // ignore
+      }
+    }
+
+    if (parser.index >= parser.source.length) {
+      return report(parser, Errors.UnterminatedRegExp);
+    }
+  }
+
+  const bodyEnd = parser.index - 1;
+
+  const enum RegexFlags {
+    Empty = 0b00000,
+    IgnoreCase = 0b00001,
+    Global = 0b00010,
+    Multiline = 0b00100,
+    Unicode = 0b10000,
+    Sticky = 0b01000,
+    DotAll = 0b1100
+  }
+
+  let mask = RegexFlags.Empty;
+  let char = parser.currentChar;
+
+  const { index: flagStart } = parser;
+
+  while (isIdentifierPart(char)) {
+    switch (char) {
+      case Chars.LowerG:
+        if (mask & RegexFlags.Global) report(parser, Errors.DuplicateRegExpFlag, 'g');
+        mask |= RegexFlags.Global;
+        break;
+
+      case Chars.LowerI:
+        if (mask & RegexFlags.IgnoreCase) report(parser, Errors.DuplicateRegExpFlag, 'i');
+        mask |= RegexFlags.IgnoreCase;
+        break;
+
+      case Chars.LowerM:
+        if (mask & RegexFlags.Multiline) report(parser, Errors.DuplicateRegExpFlag, 'm');
+        mask |= RegexFlags.Multiline;
+        break;
+
+      case Chars.LowerU:
+        if (mask & RegexFlags.Unicode) report(parser, Errors.DuplicateRegExpFlag, 'g');
+        mask |= RegexFlags.Unicode;
+        break;
+
+      case Chars.LowerY:
+        if (mask & RegexFlags.Sticky) report(parser, Errors.DuplicateRegExpFlag, 'y');
+        mask |= RegexFlags.Sticky;
+        break;
+
+      case Chars.LowerS:
+        if (mask & RegexFlags.DotAll) report(parser, Errors.DuplicateRegExpFlag, 's');
+        mask |= RegexFlags.DotAll;
+        break;
+
+      default:
+        report(parser, Errors.UnexpectedTokenRegExpFlag);
+    }
+
+    char = advanceChar(parser);
+  }
+
+  const flags = parser.source.slice(flagStart, parser.index);
+
+  const pattern = parser.source.slice(bodyStart, bodyEnd);
+
+  parser.tokenRegExp = { pattern, flags };
+
+  if (context & Context.OptionsRaw) parser.tokenRaw = parser.source.slice(parser.tokenPos, parser.index);
+
+  parser.tokenValue = validate(parser, pattern, flags);
+
+  return Token.RegularExpression;
+}
+
+/**
+ * Validates regular expressions
+ *
+ *
+ * @param state Parser instance
+ * @param context Context masks
+ * @param pattern Regexp body
+ * @param flags Regexp flags
+ */
+function validate(parser: ParserState, pattern: string, flags: string): RegExp | null | Token {
+  try {
+    return new RegExp(pattern, flags);
+  } catch (e) {
+    report(parser, Errors.UnterminatedRegExp);
+  }
+}
-- 
cgit