1 | const extend = require('./utils').extend;
|
2 |
|
3 | function isFlag(token) {
|
4 | return token.slice(0, 1) === '[' && token.slice(-1) === ']';
|
5 | }
|
6 | function isAlternation(token) {
|
7 | return token.slice(0, 1) === '(' && token.slice(-1) === ')';
|
8 | }
|
9 | function removeEmptyStrings(texts) {
|
10 | return texts.filter(text => text !== '');
|
11 | }
|
12 | function createPermutations(tokens, index) {
|
13 | if (index === tokens.length) {
|
14 | return [{ text: '', flags: {}, alternations: [] }];
|
15 | }
|
16 |
|
17 | const token = tokens[index];
|
18 | const tail = createPermutations(tokens, index + 1);
|
19 | if (isFlag(token)) {
|
20 | const flag = token.slice(1, -1);
|
21 | return tail
|
22 | .map(pattern => {
|
23 | const flags = {};
|
24 | flags[flag] = true;
|
25 | return {
|
26 | text: `${flag} ${pattern.text}`,
|
27 | flags: extend(flags, pattern.flags),
|
28 | alternations: pattern.alternations
|
29 | };
|
30 | })
|
31 | .concat(
|
32 | tail.map(pattern => {
|
33 | const flags = {};
|
34 | flags[flag] = false;
|
35 | return {
|
36 | text: pattern.text,
|
37 | flags: extend(flags, pattern.flags),
|
38 | alternations: pattern.alternations
|
39 | };
|
40 | })
|
41 | );
|
42 | } else if (isAlternation(token)) {
|
43 | return token
|
44 | .substr(1, token.length - 2)
|
45 | .split(/\|/)
|
46 | .reduce(
|
47 | (result, alternation) =>
|
48 | result.concat(
|
49 | tail.map(({ text, flags, alternations }) => ({
|
50 |
|
51 | text: alternation ? alternation + text : text.replace(/^ /, ''),
|
52 |
|
53 | flags,
|
54 | alternations: [alternation, ...alternations]
|
55 | }))
|
56 | ),
|
57 | []
|
58 | );
|
59 | } else {
|
60 | return tail.map(({ text, flags, alternations }) => ({
|
61 | text: token + text,
|
62 | flags,
|
63 | alternations
|
64 | }));
|
65 | }
|
66 | }
|
67 |
|
68 | function expandAssertion(pattern) {
|
69 | pattern = pattern.replace(/(\[[^\]]+\]) ?/g, '$1');
|
70 | const splitRegex = /\[[^\]]+\]|\([^)]+\)/g;
|
71 | let tokens = [];
|
72 | let m;
|
73 | let lastIndex = 0;
|
74 | while ((m = splitRegex.exec(pattern))) {
|
75 | tokens.push(pattern.slice(lastIndex, m.index));
|
76 | tokens.push(pattern.slice(m.index, splitRegex.lastIndex));
|
77 | lastIndex = splitRegex.lastIndex;
|
78 | }
|
79 | tokens.push(pattern.slice(lastIndex));
|
80 | tokens = removeEmptyStrings(tokens);
|
81 | const permutations = createPermutations(tokens, 0);
|
82 | permutations.forEach(permutation => {
|
83 | permutation.text = permutation.text.trim();
|
84 | if (permutation.text === '') {
|
85 |
|
86 | throw new Error('Assertion patterns must not only contain flags');
|
87 | }
|
88 | });
|
89 | return permutations;
|
90 | }
|
91 |
|
92 | module.exports = expandAssertion;
|