compose-regexp
Advanced tools
Comparing version 0.1.8 to 0.2.0
@@ -32,7 +32,14 @@ var empty = new RegExp('') | ||
var call = group.call | ||
var push = [].push | ||
function operator(suffix) { | ||
if (arguments.length === 1) return empty | ||
return new RegExp(new RegExp(call.apply(group, arguments).source + suffix)) | ||
} | ||
export function greedy(suffix) { | ||
if (!validSuffix.test(suffix)) throw new Error("Invalid suffix '" + suffix+ "'.") | ||
var args = [].slice.call(arguments, 1) | ||
if (!args.length) return empty; | ||
return new RegExp(group.apply(null, args).source + suffix) | ||
return (arguments.length === 1) | ||
? operator.bind(null, suffix) | ||
: operator.apply(null, arguments) | ||
} | ||
@@ -42,5 +49,5 @@ | ||
if (!validSuffix.test(suffix)) throw new Error("Invalid suffix '" + suffix+ "'.") | ||
var args = [].slice.call(arguments, 1) | ||
if (!args.length) return empty; | ||
return new RegExp(group.apply(null, args).source + suffix + '?') | ||
return (arguments.length === 1) | ||
? operator.bind(null, suffix+'?') | ||
: (arguments[0] = suffix + '?', operator.apply(null, arguments)) | ||
} | ||
@@ -47,0 +54,0 @@ |
@@ -20,2 +20,3 @@ (function (global, factory) { | ||
function group() { | ||
console.log('group',arguments) | ||
if (!arguments.length) return empty; | ||
@@ -39,7 +40,14 @@ return new RegExp('(?:' + [].map.call(arguments, normalize).join('') + ')') | ||
var call = group.call | ||
function operator(suffix) { | ||
console.log('op', arguments) | ||
if (arguments.length === 1) return empty | ||
return new RegExp(new RegExp(call.apply(group, arguments).source + suffix)) | ||
} | ||
function greedy(suffix) { | ||
if (!validSuffix.test(suffix)) throw new Error("Invalid suffix '" + suffix+ "'.") | ||
var args = [].slice.call(arguments, 1) | ||
if (!args.length) return empty; | ||
return new RegExp(group.apply(null, args).source + suffix) | ||
return (arguments.length === 1) | ||
? operator.bind(null, suffix) | ||
: operator.apply(null, arguments) | ||
} | ||
@@ -49,5 +57,5 @@ | ||
if (!validSuffix.test(suffix)) throw new Error("Invalid suffix '" + suffix+ "'.") | ||
var args = [].slice.call(arguments, 1) | ||
if (!args.length) return empty; | ||
return new RegExp(group.apply(null, args).source + suffix + '?') | ||
return (arguments.length === 1) | ||
? operator.bind(null, suffix+'?') | ||
: (arguments[0] = suffix + '?', operator.apply(null, arguments)) | ||
} | ||
@@ -54,0 +62,0 @@ |
@@ -1,2 +0,1 @@ | ||
/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/ | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define("compose-regexp",["exports"],n):n(e.composeRegexp={})}(this,function(e){"use strict";function n(e){return e instanceof RegExp?e.source:(e+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function t(){return arguments.length?new RegExp("(?:"+[].map.call(arguments,n).join("|")+")"):p}function r(){return arguments.length?new RegExp("(?:"+[].map.call(arguments,n).join("")+")"):p}function u(){return arguments.length?new RegExp([].map.call(arguments,n).join("")):p}function a(e){if(!f.test(e))throw new Error("Invalid suffix '"+e+"'.");var n=[].slice.call(arguments,1);return n.length?new RegExp(r.apply(null,n).source+e):p}function o(e){if(!f.test(e))throw new Error("Invalid suffix '"+e+"'.");var n=[].slice.call(arguments,1);return n.length?new RegExp(r.apply(null,n).source+e+"?"):p}function g(e){return new RegExp("\\"+e)}function l(){return arguments.length?new RegExp("(?="+[].map.call(arguments,n).join("")+")"):p}function s(){return arguments.length?new RegExp("(?!"+[].map.call(arguments,n).join("")+")"):p}function i(e){var t,r=[].slice.call(arguments,1);return t=r.length?r.map(n).join(""):"",new RegExp(t,e)}function c(){return arguments.length?new RegExp("("+[].map.call(arguments,n).join("")+")"):new RegExp("()")}var p=new RegExp(""),f=u(/^/,t("+","*","?",/\{\s*\d+\s*,?\s*\d*\s*\}/),/$/);e.either=t,e.group=r,e.sequence=u,e.greedy=a,e.frugal=o,e.ref=g,e.lookAhead=l,e.avoid=s,e.flags=i,e.capture=c}); | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define("compose-regexp",["exports"],n):n(e.composeRegexp={})}(this,function(e){"use strict";function n(e){return e instanceof RegExp?e.source:(e+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function t(){return arguments.length?new RegExp("(?:"+[].map.call(arguments,n).join("|")+")"):s}function o(){return console.log("group",arguments),arguments.length?new RegExp("(?:"+[].map.call(arguments,n).join("")+")"):s}function l(){return arguments.length?new RegExp([].map.call(arguments,n).join("")):s}function r(e){return console.log("op",arguments),1===arguments.length?s:new RegExp(new RegExp(d.apply(o,arguments).source+e))}function u(e){if(!x.test(e))throw new Error("Invalid suffix '"+e+"'.");return 1===arguments.length?r.bind(null,e):r.apply(null,arguments)}function p(e){if(!x.test(e))throw new Error("Invalid suffix '"+e+"'.");return 1===arguments.length?r.bind(null,e+"?"):(arguments[0]=e+"?",r.apply(null,arguments))}function i(e){return new RegExp("\\"+e)}function c(){return arguments.length?new RegExp("(?="+[].map.call(arguments,n).join("")+")"):s}function g(){return arguments.length?new RegExp("(?!"+[].map.call(arguments,n).join("")+")"):s}function f(e){var t,o=[].slice.call(arguments,1);return t=o.length?o.map(n).join(""):"",new RegExp(t,e)}function a(){return arguments.length?new RegExp("("+[].map.call(arguments,n).join("")+")"):new RegExp("()")}var s=new RegExp(""),x=l(/^/,t("+","*","?",/\{\s*\d+\s*,?\s*\d*\s*\}/),/$/),d=o.call;e.either=t,e.group=o,e.sequence=l,e.greedy=u,e.frugal=p,e.ref=i,e.lookAhead=c,e.avoid=g,e.flags=f,e.capture=a}); |
{ | ||
"name": "compose-regexp", | ||
"version": "0.1.8", | ||
"version": "0.2.0", | ||
"description": "A set of functions to build and compose complex regular expressions", | ||
@@ -5,0 +5,0 @@ "main": "compose-regexp.js", |
@@ -0,9 +1,19 @@ | ||
# compose-regexp.js | ||
A set of functions to build and compose complex regular expressions in JavaScript. | ||
Build and compose *maintainable* regular expressions in JavaScript. | ||
Works nicely with [verbal expressions](https://github.com/VerbalExpressions/JSVerbalExpressions), even though the target user is likely different. | ||
Regular expressions don't do justice to regular grammars. | ||
The goal of this library is to enable advanced RegExp users to write maintainable lexers and parsers. A reasonable understanding of the parsing model of regexps is a prerequisite. | ||
- The regular grammar/language formalism is all about [expression composition](https://en.wikipedia.org/w/index.php?title=Regular_language&oldid=748009543#Formal_definition). | ||
- Yet RegExps were designed as a [write-only syntax for command line tools](https://en.wikipedia.org/w/index.php?title=Regular_expression&oldid=762174774#History) like `ed` and `grep`. | ||
- Building large expressions from smaller, abstracted patterns is not possible using RegExp literals. | ||
This makes complex RegExps hard to read, debug and modify... | ||
`compose-regexp` to the rescue! | ||
It doesn't make regular grammars more powerful, they are still [fundamentally limited](https://en.wikipedia.org/w/index.php?title=Chomsky_hierarchy&oldid=762040114#The_hierarchy), but since they are ubiquitous, we may as well have better tooling to implement them... | ||
## Usage | ||
@@ -18,6 +28,6 @@ | ||
sequence, either, capture, | ||
ref, greedy | ||
ref, greedy, flags, avoid | ||
} from "compose-regexp"; // can be required too | ||
// the example that made me write this, in order to ~parse JS. | ||
// the example that made me write this, in order to ~lex JS. | ||
// It matches braces in source code, but skips comments and strings. | ||
@@ -117,3 +127,3 @@ let matcher = flags('gm', | ||
#### greedy(suffix, regexprs...) | ||
#### greedy(suffix, regexprs...), greedy(suffix)(regexprs...) | ||
@@ -125,7 +135,7 @@ Valid suffixes: (`?`, `*`, `+`, `{n}`, `{n,}` and `{m, n}`) | ||
/(?:a|b|c)*/ | ||
> maybe = greedy.bind(null, '?'); maybe(either('a', 'b')) | ||
> maybe = greedy('?'); maybe(either('a', 'b')) | ||
/(?:a|b)?/ | ||
``` | ||
#### frugal(suffix, regexprs...) | ||
#### frugal(suffix, regexprs...), frugal(suffix)(regexprs...) | ||
@@ -132,0 +142,0 @@ Like `greedy()` but for non-greedy operators (`??`, `*?`, `+?`, `{n}?`, `{n,}?` and `{m, n}?`). |
@@ -1,21 +0,24 @@ | ||
var sane = require('../') | ||
var CR = require('../') | ||
function eq(a, b) { | ||
function req(a, b) { | ||
if (a.source !== b.source) throw new Error ("expected " + b.source + " got " + a.source) | ||
} | ||
function eq(a, b) { | ||
if (a !== b) throw new Error("expected " + b + " got " + a) | ||
} | ||
var either = sane.either | ||
var group = sane.group | ||
var sequence = sane.sequence | ||
var greedy = sane.greedy | ||
var frugal = sane.frugal | ||
var ref = sane.ref | ||
var lookAhead = sane.lookAhead | ||
var avoid = sane.avoid | ||
var flags = sane.flags | ||
var capture = sane.capture | ||
var either = CR.either | ||
var group = CR.group | ||
var sequence = CR.sequence | ||
var greedy = CR.greedy | ||
var frugal = CR.frugal | ||
var ref = CR.ref | ||
var lookAhead = CR.lookAhead | ||
var avoid = CR.avoid | ||
var flags = CR.flags | ||
var capture = CR.capture | ||
eq(either('a'), /(?:a)/) | ||
eq(either('a','b'), /(?:a|b)/) | ||
eq(either('a', 'b', 'c'), /(?:a|b|c)/) | ||
req(either('a'), /(?:a)/) | ||
req(either('a','b'), /(?:a|b)/) | ||
req(either('a', 'b', 'c'), /(?:a|b|c)/) | ||
@@ -25,3 +28,3 @@ // normalization | ||
either, group, sequence, | ||
greedy.bind(null, '*'), frugal.bind(null, '+'), | ||
greedy('*'), frugal('+'), | ||
lookAhead, avoid, | ||
@@ -31,50 +34,52 @@ flags.bind(null, ''), capture | ||
// normalization | ||
eq(m(/\./), m('.')) | ||
req(m(/\./), m('.')) | ||
// empty arg list | ||
if (m !== capture) | ||
eq(m(), new RegExp('')) | ||
req(m(), new RegExp('')) | ||
else | ||
eq(m(), /()/) | ||
req(m(), /()/) | ||
}) | ||
eq(sequence('a'), /a/) | ||
eq(sequence('a', 'b'), /ab/) | ||
eq(sequence('a', 'b', 'c'), /abc/) | ||
eq(sequence(/^/, 'b', /$/), /^b$/) | ||
req(sequence('a'), /a/) | ||
req(sequence('a', 'b'), /ab/) | ||
req(sequence('a', 'b', 'c'), /abc/) | ||
req(sequence(/^/, 'b', /$/), /^b$/) | ||
eq(group('a'), /(?:a)/) | ||
eq(group('a', 'b'), /(?:ab)/) | ||
eq(group('a', 'b', 'c'), /(?:abc)/) | ||
req(group('a'), /(?:a)/) | ||
req(group('a', 'b'), /(?:ab)/) | ||
req(group('a', 'b', 'c'), /(?:abc)/) | ||
eq(avoid('a'), /(?!a)/) | ||
eq(avoid('a', 'b'), /(?!ab)/) | ||
eq(avoid('a', 'b', 'c'), /(?!abc)/) | ||
req(avoid('a'), /(?!a)/) | ||
req(avoid('a', 'b'), /(?!ab)/) | ||
req(avoid('a', 'b', 'c'), /(?!abc)/) | ||
eq(lookAhead('a'), /(?=a)/) | ||
eq(lookAhead('a', 'b'), /(?=ab)/) | ||
eq(lookAhead('a', 'b', 'c'), /(?=abc)/) | ||
req(lookAhead('a'), /(?=a)/) | ||
req(lookAhead('a', 'b'), /(?=ab)/) | ||
req(lookAhead('a', 'b', 'c'), /(?=abc)/) | ||
eq(capture('a'), /(a)/) | ||
eq(capture('a', 'b'), /(ab)/) | ||
eq(capture('a', 'b', 'c'), /(abc)/) | ||
req(capture('a'), /(a)/) | ||
req(capture('a', 'b'), /(ab)/) | ||
req(capture('a', 'b', 'c'), /(abc)/) | ||
eq(ref(1), /\1/) | ||
eq(ref(9), /\9/) | ||
req(ref(1), /\1/) | ||
req(ref(9), /\9/) | ||
eq(greedy('?', /foo/), /(?:foo)?/) | ||
eq(greedy('*', /foo/), /(?:foo)*/) | ||
eq(greedy('+', /foo/), /(?:foo)+/) | ||
req(greedy('?', /foo/), /(?:foo)?/) | ||
req(greedy('*', /foo/), /(?:foo)*/) | ||
req(greedy('+', /foo/), /(?:foo)+/) | ||
eq(frugal('?', /foo/), /(?:foo)??/) | ||
eq(frugal('*', /foo/), /(?:foo)*?/) | ||
eq(frugal('+', /foo/), /(?:foo)+?/) | ||
req(frugal('?', /foo/), /(?:foo)??/) | ||
req(frugal('*', /foo/), /(?:foo)*?/) | ||
req(frugal('+', /foo/), /(?:foo)+?/) | ||
// this is a bit of a hack to take advantage of `eq` as assert equals. | ||
eq(sequence(flags('m', /o/).multiline), /true/) | ||
eq(sequence(flags('i', /o/).multiline), /false/) | ||
req(sequence(flags('m', /o/).multiline), /true/) | ||
req(sequence(flags('i', /o/).multiline), /false/) | ||
;['*', '+', '?', '{2}', '{2,}', '{2,4}'].forEach(function(suffix){ | ||
greedy(suffix, 'a') | ||
frugal(suffix, 'a') | ||
req(greedy(suffix, 'a'), {source: '(?:a)' + suffix}) | ||
req(frugal(suffix, 'a'), {source: '(?:a)' + suffix + '?'}) | ||
req(greedy(suffix)('a'), {source: '(?:a)' + suffix}) | ||
req(frugal(suffix)('a'), {source: '(?:a)' + suffix + '?'}) | ||
}) | ||
@@ -86,16 +91,32 @@ | ||
try { | ||
greedy(suffix + '?', 'a') | ||
greedy(suffix + '?', 'a') | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(sequence(caught), /true/) | ||
eq(caught, true) | ||
caught = false | ||
try { | ||
frugal(suffix + '?', 'a') | ||
greedy(suffix + '?') | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(sequence(caught), /true/) | ||
eq(caught, true) | ||
caught = false | ||
try { | ||
frugal(suffix + '?', 'a') | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(caught, true) | ||
caught = false | ||
try { | ||
frugal(suffix + '?') | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(caught, true) | ||
}) | ||
@@ -107,16 +128,32 @@ | ||
try { | ||
greedy(suffix, 'a') | ||
greedy(suffix, 'a') | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(sequence(caught), /true/) | ||
eq(caught, true) | ||
caught = false | ||
try { | ||
frugal(suffix, 'a') | ||
greedy(suffix) | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(sequence(caught), /true/) | ||
eq(caught, true) | ||
caught = false | ||
try { | ||
frugal(suffix, 'a') | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(caught, true) | ||
caught = false | ||
try { | ||
frugal(suffix) | ||
} catch (e) { | ||
caught = true | ||
} | ||
eq(caught, true) | ||
}) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23283
9
281
214