Repository: DmitrySoshnikov/regexp-tree
Pull request #232 (2021-09-19 02:29:40)

Allow escaped hyphens in character classes
Sorry for #231. I'm still getting a hang of publishing packages and open source in general.

This PR modifies the parsing grammar to allow escaped hyphens inside character classes. All tests pass and I've even added a new one.

For the time being, I can `npm install https://github.com/just1ngray/regexp-tree` and it's working for my purposes. Just thought I'd create a PR in case it'd help anyone else.


Patch:
diff --git a/src/parser/generated/regexp-tree.js b/src/parser/generated/regexp-tree.js
index c5545e7..faf9d33 100644
--- a/src/parser/generated/regexp-tree.js
+++ b/src/parser/generated/regexp-tree.js
@@ -374,7 +374,10 @@ const lexRules = [[/^#[^\n]+/, function() { /* skip comments */ }],
 [/^\\[\^\$\.\*\+\?\(\)\\\[\]\{\}\|\/]/, function() { return 'ESC_CHAR' }],
 [/^\\[^*?+\[()\\|]/, function() { 
                                       const s = this.getCurrentState();
-                                      if (s === 'u' || s === 'xu' || s === 'u_class') {
+                                      if (s === 'u_class' && yytext === "\\-") {
+                                        return 'ESC_CHAR';
+                                      }
+                                      else if (s === 'u' || s === 'xu' || s === 'u_class') {
                                         throw new SyntaxError(`invalid Unicode escape ${yytext}`);
                                       }
                                       return 'ESC_CHAR';
diff --git a/src/parser/regexp.bnf b/src/parser/regexp.bnf
index c62f061..fcb4009 100644
--- a/src/parser/regexp.bnf
+++ b/src/parser/regexp.bnf
@@ -128,7 +128,10 @@ NAME                    \w+
 
 {ESC}{CHAR}                         {
                                       const s = this.getCurrentState();
-                                      if (s === 'u' || s === 'xu' || s === 'u_class') {
+                                      if (s === 'u_class' && yytext === "\\-") {
+                                        return 'ESC_CHAR';
+                                      }
+                                      else if (s === 'u' || s === 'xu' || s === 'u_class') {
                                         throw new SyntaxError(`invalid Unicode escape ${yytext}`);
                                       }
                                       return 'ESC_CHAR';


Test patch:
diff --git a/src/parser/__tests__/parser-basic-test.js b/src/parser/__tests__/parser-basic-test.js
index ed57b1c..ba4348b 100644
--- a/src/parser/__tests__/parser-basic-test.js
+++ b/src/parser/__tests__/parser-basic-test.js
@@ -135,6 +135,38 @@ describe('basic', () => {
       },
       flags: 'i',
     });
+
+    expect(re(/[a\-z]/u)).toEqual({
+      type: 'RegExp',
+      body: {
+        type: 'CharacterClass',
+        expressions: [
+          {
+            type: 'Char',
+            value: 'a',
+            symbol: 'a',
+            kind: 'simple',
+            codePoint: 'a'.codePointAt(0),
+          },
+          {
+            type: 'Char',
+            value: '-',
+            symbol: '-',
+            kind: 'simple',
+            escaped: true,
+            codePoint: '-'.codePointAt(0),
+          },
+          {
+            type: 'Char',
+            value: 'z',
+            symbol: 'z',
+            kind: 'simple',
+            codePoint: 'z'.codePointAt(0),
+          },
+        ],
+      },
+      flags: 'u',
+    });
   });
 
   it('empty class', () => {