diff --git a/src/optimizer/transforms/__tests__/remove-empty-group-transform-test.js b/src/optimizer/transforms/__tests__/remove-empty-group-transform-test.js new file mode 100644 index 0000000..dfcbe8f --- /dev/null +++ b/src/optimizer/transforms/__tests__/remove-empty-group-transform-test.js @@ -0,0 +1,39 @@ +/** + * The MIT License (MIT) + * Copyright (c) 2017-present Dmitry Soshnikov + */ + +'use strict'; + +const {transform} = require('../../../transform'); +const removeEmptyGroup = require('../remove-empty-group-transform'); + +describe('remove empty groups', () => { + + it('removes empty groups', () => { + const re = transform(/a(?:)b/, [ + removeEmptyGroup + ]); + expect(re.toString()).toBe('/ab/'); + + const re2 = transform(/((?:))/, [ + removeEmptyGroup + ]); + expect(re2.toString()).toBe('/()/'); + }); + + it('does not remove empty regexp', () => { + const re = transform(/(?:)/, [ + removeEmptyGroup + ]); + expect(re.toString()).toBe('/(?:)/'); + }); + + it('removes empty group quantifier', () => { + const re = transform(/(?:)+/, [ + removeEmptyGroup + ]); + expect(re.toString()).toBe('/(?:)/'); + }); + +}); \ No newline at end of file diff --git a/src/optimizer/transforms/index.js b/src/optimizer/transforms/index.js index 2027ccd..e04f411 100644 --- a/src/optimizer/transforms/index.js +++ b/src/optimizer/transforms/index.js @@ -30,6 +30,9 @@ module.exports = [ // (a|b|c) -> [abc] require('./group-single-chars-to-char-class'), + // (?:)a -> a + require('./remove-empty-group-transform'), + // (?:a) -> a require('./ungroup-transform') ]; \ No newline at end of file diff --git a/src/optimizer/transforms/remove-empty-group-transform.js b/src/optimizer/transforms/remove-empty-group-transform.js new file mode 100644 index 0000000..bd8ae34 --- /dev/null +++ b/src/optimizer/transforms/remove-empty-group-transform.js @@ -0,0 +1,34 @@ +/** + * The MIT License (MIT) + * Copyright (c) 2017-present Dmitry Soshnikov + */ + +'use strict'; + +/** + * A regexp-tree plugin to remove non-capturing empty groups. + * + * /(?:)a/ -> /a/ + * /a|(?:)/ -> /a|/ + */ + +module.exports = { + Group(path) { + const {node, parent} = path; + const childPath = path.getChild(); + + if (node.capturing || childPath) { + return; + } + + if (parent.type === 'Repetition') { + + path.getParent().replace(node); + + } else if (parent.type !== 'RegExp') { + + path.remove(); + + } + } +};