{"id":15415872,"url":"https://github.com/davidje13/revexp","last_synced_at":"2026-05-17T00:04:56.530Z","repository":{"id":65489886,"uuid":"406140916","full_name":"davidje13/RevExp","owner":"davidje13","description":"Given a regular expression, solves for possible matching input strings","archived":false,"fork":false,"pushed_at":"2023-10-23T02:20:09.000Z","size":132,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-08T14:02:52.430Z","etag":null,"topics":["regular-expression"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidje13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-13T21:56:47.000Z","updated_at":"2021-12-06T00:18:50.000Z","dependencies_parsed_at":"2024-10-01T17:10:05.167Z","dependency_job_id":"e37c6dcc-5999-4058-83e9-828a4a9ee2db","html_url":"https://github.com/davidje13/RevExp","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FRevExp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FRevExp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FRevExp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FRevExp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidje13","download_url":"https://codeload.github.com/davidje13/RevExp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244618448,"owners_count":20482319,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["regular-expression"],"created_at":"2024-10-01T17:10:03.728Z","updated_at":"2025-10-11T13:11:36.716Z","avatar_url":"https://github.com/davidje13.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RevExp\n\nThis library calculates the possible inputs for a given regular expression.\n\nThe supported syntax is modelled on the standard Javascript `RegExp` object's syntax.\n\nYou can [try it online](https://regex.davidje13.com/) or in the terminal:\n\n```shell\nnpx revexp 'H(alp|el{2,}[o]) (Wor|wo)lds?' '??????W????'\n```\n\n## Supported Features\n\n| Pattern Feature          | Examples                     | Support       |\n|--------------------------|------------------------------|---------------|\n| Character classes        | `a` `[aeiou]` `[^a-z]` `\\d`  | \u0026#x2705; Full |\n| Character escapes        | `\\u0020` `\\\\` `\\n` `\\(`      | \u0026#x2705; Full |\n| Unicode properties       | `\\p{Letter}` `\\p{RGI_Emoji}` | \u0026#x274C; None |\n| Set notation (`v`)       | `[[ab]\u0026\u0026[bc]]` `[[ab]--a]`   | \u0026#x2705; Full |\n| String literals (`v`)    | `[\\q{ab\\|cd}]`               | \u0026#x2705; Full |\n| Branching                | `x\\|y`                       | \u0026#x2705; Full |\n| Anchors                  | `^` `$`                      | \u0026#x2705; Full |\n| Word boundary assertions | `\\b` `\\B`                    | Partial \u0026dagger; |\n| Standard quantifiers     | `a*` `a+` `a?`               | \u0026#x2705; Full |\n| Range quantifiers        | `a{2}` `a{2,}` `a{2,3}`      | \u0026#x2705; Full |\n| Lazy quantifiers         | `a+?` `a*?` `a??` `a{2,}?`   | \u0026#x2705; Full |\n| Possessive quantifiers   | `a++` `a*+` `a?+` `a{2,}+`   | \u0026#x274C; None |\n| Groups                   | `(abc)` `(?\u003cname\u003eabc)`       | \u0026#x2705; Full |\n| Backreferences           | `(abc)\\1` `(?\u003cx\u003eabc)\\k\u003cx\u003e`   | Partial \u0026ddagger; |\n| Non-capturing groups     | `(?:abc)`                    | \u0026#x2705; Full |\n| Positive lookaheads      | `(?=abc)`                    | \u0026#x274C; None |\n| Negative lookaheads      | `(?!abc)`                    | \u0026#x274C; None |\n| Positive lookbehinds     | `(?\u003c=abc)`                   | \u0026#x274C; None |\n| Negative lookbehinds     | `(?\u003c!abc)`                   | \u0026#x274C; None |\n\n\u0026dagger;: Two passes may be required to fully narrow an input when using this feature.\n\n\u0026ddagger;: Backreferences are currently handled as if the group were repeated (with an optional\nqualifier), meaning the syntax is accepted and any full or partial valid input will be accepted,\nbut full or partial invalid inputs may not be rejected, and the library may not be able to fully\nnarrow inputs when using patterns which include this feature.\n\n| Flag | Meaning                        | Support          |\n|------|--------------------------------|------------------|\n| `d`  | Output substring match indices | Not applicable   |\n| `g`  | Global search                  | Not applicable   |\n| `i`  | Case-insensitive search        | None (`false`)   |\n| `m`  | Multi-line search              | \u0026#x2705; Full    |\n| `s`  | `.` matches newline            | \u0026#x2705; Full    |\n| `u`  | Unicode mode                   | None (`false`)   |\n| `v`  | Unicode sets                   | Partial \u0026dagger; |\n| `y`  | Sticky search                  | Not applicable   |\n\n\u0026dagger;: Sets and string literals are supported, but unicode string attributes are not.\n\n## Usage\n\n### Library\n\n```shell\nnpm install --save revexp\n```\n\n```javascript\nimport RevExp from 'revexp';\n\n// compile the pattern\nconst pattern = new RevExp('a[bc]|x[yz]');\n\n// provide already known information - the first character is unknown, the second must be \"c\"\nconst known = RevExp.string('?c', '?');\n\n// resolve as much of the data as possible\nconst resolved = pattern.reverse(known);\n\n// print it in a human-friendly format\nconsole.log(String(resolved)); // \"ac\"\n```\n\n### CLI\n\n```shell\nnpx revexp 'a[bc]|x[yz]' '?c'\n```\n\nYou can also optionally change the \"unknown character\":\n\n```shell\nnpx revexp -u'.' 'a[bc]|x[yz]' '.c'\n```\n\n## Examples\n\n| pattern              | input      | output                 |\n|----------------------|------------|------------------------|\n| `(hello\\|hi)`        | `??`       | `hi`                   |\n| `(hello\\|hi)`        | `?????`    | `hello`                |\n| `(hello\\|hi) *`      | `?????`    | `h[ei][ l][ l][ o]`    |\n| `(hello\\|hi) *`      | `???? `    | `hi  `                 |\n| `(a[bc]d\\|e(f\\|gh))` | `???`      | `[ae][bcg][dh]`        |\n| `(a[bc]d\\|e(f\\|gh))` | `?g?`      | `egh`                  |\n| ` *a{4} +a{2} *`     | `????????` | `[ a]aaa[ a][ a]a[ a]` |\n\n## Performance and Security Considerations\n\nMatching is performed using an algorithm which executes in polynomial time on the size of the input\nfor a given pattern. This means it is not vulnerable to catastrophic backtracking (but note that\nuntrusted patterns can take arbitrarily long to compile and use an unbounded amount of memory).\n\n## API\n\n### `RevExp`\n\nThis object stores a compiled regular expression. It is analogous to Javascript's native `RegExp`.\nConstruction is expensive, as it must compile the regular expression into a graph form. Once created,\nthe `RevExp` object can be used repeatedly.\n\n#### constructor\n\n```javascript\nconst revexp = new RevExp('pattern');\nconst revexp = new RevExp(/existing regex/);\nconst revexp = RevExp.compile('pattern');\n```\n\nCreates a new `RevExp` object, compiling the pattern into an internal graph ready for use.\nThe `.compile` form is just an alias; functionally both forms are the same.\n\nIf you pass in a `RegExp` or `RevExp` object, the pattern will be extracted and compiled.\nNote that this project is not 100% compatible with `RegExp` features (see above for details).\n\n#### `RevExp.string(input[, unknown])`\n\n```javascript\nconst characterClassString = RevExp.string('foobar');\nconst characterClassString = RevExp.string('foob**', '*');\nconst characterClassString = RevExp.string(myCharClassArray);\n```\n\nConverts `input` into a character class array.\n\nWhen invoked with a string `input` and no `unknown` parameter, the string is taken literally\n(i.e. it assumes all characters are known).\n\nWhen invoked with a string `input` and an `unknown` parameter, any occurence of `unknown`\nwithin `input` is replaced with `CharacterClass.ANY`.\n\nWhen invoked with an existing character class array, this will copy the array but make no\nchanges to the values (this can be used to avoid mutating the original, for example).\n\nThe returned array has an overloaded `toString` which allows easy pretty-printing, and an\n`isSingular` method which returns true if all the contained character classes are singular.\n\n#### `.test(input[, unknown])`\n\n```javascript\nconst success = myRevExp.test('foobar');\nconst success = myRevExp.test('foob**', '*');\nconst success = myRevExp.test(myCharClassArray);\n```\n\nTests if `input` matches (or can match) the regular expression. Returns `true` if a match\nis possible, or `false` if no match is possible.\n\nFor an explanation of the `input` and `unknown` parameters, see the information for\n`RevExp.string` above.\n\nFor the most control, invoke with a character class array. This allows you to pass in exact\nranges for each character. For example:\n\n```javascript\nconst input = [\n  RevExp.CharacterClass.of('f'), // literal 'f'\n  RevExp.CharacterClass.of('o'),\n  RevExp.CharacterClass.of('o'),\n  RevExp.CharacterClass.of('bz'), // 'b' or 'z'\n  RevExp.CharacterClass.WORD, // a-zA-Z0-9_\n  RevExp.CharacterClass.ANY, // anything\n];\n// input is equivalent to a pattern of 'foo[bz]\\w.'\nconst success = myRevExp.test(input);\n```\n\n##### Examples\n\n```javascript\nconst revexp = new RevExp('(hello|hi+)');\n\nconsole.log(revexp.test('hello')); // true\nconsole.log(revexp.test('hi')); // true\nconsole.log(revexp.test('nope')); // false\nconsole.log(revexp.test('words hello words')); // false\nconsole.log(revexp.test('h????')); // false\nconsole.log(revexp.test('he???', '?')); // true\nconsole.log(revexp.test('he??', '?')); // false\n```\n\n#### `.reverse(input[, unknown])`\n\n```javascript\nconst restrictions = myRevExp.reverse('foobar');\nconst restrictions = myRevExp.reverse('foob**', '*');\nconst restrictions = myRevExp.reverse(myCharClassArray);\n```\n\nReturns a character class array with the tightest possible restrictions on the characters\nbased on the regular expression and the given `input`. If no matches are possible, returns\n`null`.\n\nFor an explanation of the `input` and `unknown` parameters, see the information for\n`RevExp.string` above.\n\nThe returned array has an overloaded `toString` which allows easy pretty-printing, and an\n`isSingular` method which returns true if all the contained character classes are singular.\n\n##### Examples\n\n```javascript\nconst revexp = new RevExp('(hello|hi+)');\n\nconsole.log(String(revexp.reverse('hello'))); // hello\nconsole.log(String(revexp.reverse('nope'))); // null\nconsole.log(String(revexp.reverse('he???'))); // null\nconsole.log(String(revexp.reverse('he???', '?'))); // hello\nconsole.log(String(revexp.reverse('h????', '?'))); // h[ei][il][il][io]\n```\n\n### `RevExp.CharacterClass`\n\nThis object stores character class information (e.g. `[a-z]`). It also has various\nconvenience constants defined for common character classes.\n\nThe `CharacterClass` object is immutable.\n\n#### constants\n\n```javascript\nRevExp.CharacterClass.ANY     // .\nRevExp.CharacterClass.NONE    // [^]\nRevExp.CharacterClass.NUMERIC // [0-9]\nRevExp.CharacterClass.WORD    // [a-zA-Z0-9_]\nRevExp.CharacterClass.NEWLINE // various unicode newline characters\nRevExp.CharacterClass.SPACE   // various unicode space characters\n```\n\n#### constructor\n\nThere are various helpers available for building custom `CharacterClass`es:\n\n```javascript\nRevExp.CharacterClass.of('c')\nRevExp.CharacterClass.of('ax')\nRevExp.CharacterClass.of(['a', 'x'])\nRevExp.CharacterClass.ofCode(0x20)\nRevExp.CharacterClass.range('a', 'z')\nRevExp.CharacterClass.union(cc1, cc2, cc3, ...)\n```\n\n#### `toString`\n\nAs a convenience, `CharacterClass` has a `toString` which will render the class in the\nstandard regular expression format;\n\n```javascript\nconsole.log(String(RevExp.CharacterClass.of('c'))) // 'c'\nconsole.log(String(RevExp.CharacterClass.of('ax'))) // '[ax]'\nconsole.log(String(RevExp.CharacterClass.range('a', 'z'))) // '[a-z]'\nconsole.log(String(RevExp.CharacterClass.of('abcdz'))) // '[a-dz]'\nconsole.log(String(RevExp.CharacterClass.of('a').inverse())) // '[^a]'\n```\n\n#### `includes(char)`\n\nReturns `true` if the character class contains the given character.\n\n#### `isEmpty()`\n\nReturns `true` if the character class contains no characters (i.e. is impossible).\n\n#### `isSingular()`\n\nReturns `true` if the character class contains exactly one character (i.e. is fully resolved).\n\n#### `singularChar()`\n\nReturns the single character represented by this character class. If the class represents more\nthan one character (or no characters), this throws an error.\n\n#### `intersects(other)`\n\nReturns `true` if there is any overlap between the two character classes.\n\n#### `intersect(other)`\n\nReturns a new character class which contains only the characters shared by both character classes.\n\n#### `union(other)`\n\nReturns a new character class which contains all characters contained in either character class.\n\n#### `rangeTo(other)`\n\nReturns a new character class which represents the range of characters from the current character\nto the target character (inclusive at both sides). The order does not matter.\n\nThis method can only be invoked on `singular` character classes.\n\n#### `inverse()`\n\nReturns a new character class which is the inverse of the current class (i.e. any character in\nthis class is not in the returned class, and vice-versa).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Frevexp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidje13%2Frevexp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Frevexp/lists"}