-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetPreparedOptions.ts
More file actions
115 lines (97 loc) · 2.79 KB
/
getPreparedOptions.ts
File metadata and controls
115 lines (97 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import type {
Key,
Options,
PreparedComment,
PreparedOptions,
PreparedStatement,
PreparedToken,
TokenWithKey,
} from './types';
/**
* Get internal prepared options from public options.
*/
export const getPreparedOptions = <Context>({
comments = [],
onError,
regexpFlags = 'gmu',
statements = [],
}: Options<Context>): PreparedOptions<Context> => {
const commentsKeys: Key[] = [];
const firstTokens: TokenWithKey[] = [];
const firstTokensAfterComments: TokenWithKey[] = [];
let keyIndex = 1;
const openTokens: TokenWithKey[] = [];
const preparedComments = {__proto__: null} as unknown as Record<Key, PreparedComment<Context>>;
const preparedStatements = {__proto__: null} as unknown as Record<
Key,
PreparedStatement<Context>
>;
const statementsKeys: Key[] = [];
for (const {
onError,
onParse,
tokens: [open, close],
} of comments) {
const closeRegExp = createRegExp(regexpFlags, ['', close]);
const key: Key = `parseStatementsPackageComment${keyIndex++}`;
commentsKeys.push(key);
openTokens.push([key, open]);
preparedComments[key] = {closeRegExp, onError, onParse};
}
for (const {
canIncludeComments,
onError,
onParse,
tokens: [firstToken, ...restTokens],
shouldSearchBeforeComments,
} of statements) {
const statementKey: Key = `parseStatementsPackageStatement${keyIndex++}`;
const tokens: PreparedToken[] = [];
(shouldSearchBeforeComments ? firstTokens : firstTokensAfterComments).push([
statementKey,
firstToken,
]);
statementsKeys.push(statementKey);
for (const nextToken of restTokens) {
const nextTokenKey: Key = `parseStatementsPackageStatementPart${keyIndex++}`;
const regexpTokens: TokenWithKey[] = [[nextTokenKey, nextToken]];
if (canIncludeComments) {
regexpTokens[shouldSearchBeforeComments ? 'push' : 'unshift'](...openTokens);
}
const nextTokenRegExp = createRegExp(regexpFlags, ...regexpTokens);
tokens.push({nextTokenKey, nextTokenRegExp});
}
preparedStatements[statementKey] = {onError, onParse, tokens};
}
const nextStatementRegExp = createRegExp(
regexpFlags,
...firstTokens,
...openTokens,
...firstTokensAfterComments,
);
return {
commentsKeys,
nextStatementRegExp,
onError,
preparedComments,
preparedStatements,
statementsKeys,
};
};
/**
* Creates regexp by tokens.
*/
const createRegExp = (flags: string, ...tokens: readonly TokenWithKey[]): RegExp => {
if (!tokens[0]) {
return emptyRegExp;
}
let source = tokens[0][1];
if (tokens[0][0] !== '') {
source = tokens.map(([key, token]) => `(?<${key}>${token})`).join('|');
}
return new RegExp(source, flags);
};
/**
* Empty regexp that match only the empty string.
*/
const emptyRegExp = /^$/g;