| /** | |
| * Get internal prepared options from public options. | |
| */ | |
| export const getPreparedOptions = ({ comments = [], onError, statements = [], }) => { | |
| const commentsKeys = []; | |
| const firstTokens = []; | |
| const firstTokensAfterComments = []; | |
| let keyIndex = 1; | |
| const openTokens = []; | |
| const preparedComments = { __proto__: null }; | |
| const preparedStatements = { __proto__: null }; | |
| const statementsKeys = []; | |
| for (const { onError, onParse, tokens: [open, close], } of comments) { | |
| const closeRegExp = createRegExp(['', close]); | |
| const 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 = `parseStatementsPackageStatement${keyIndex++}`; | |
| const tokens = []; | |
| (shouldSearchBeforeComments ? firstTokens : firstTokensAfterComments).push([ | |
| statementKey, | |
| firstToken, | |
| ]); | |
| statementsKeys.push(statementKey); | |
| for (const nextToken of restTokens) { | |
| const nextTokenKey = `parseStatementsPackageStatementPart${keyIndex++}`; | |
| const regexpTokens = [[nextTokenKey, nextToken]]; | |
| if (canIncludeComments) { | |
| regexpTokens[shouldSearchBeforeComments ? 'push' : 'unshift'](...openTokens); | |
| } | |
| const nextTokenRegExp = createRegExp(...regexpTokens); | |
| tokens.push({ nextTokenKey, nextTokenRegExp }); | |
| } | |
| preparedStatements[statementKey] = { onError, onParse, tokens }; | |
| } | |
| const nextStatementRegExp = createRegExp(...firstTokens, ...openTokens, ...firstTokensAfterComments); | |
| return { | |
| commentsKeys, | |
| nextStatementRegExp, | |
| onError, | |
| preparedComments, | |
| preparedStatements, | |
| statementsKeys, | |
| }; | |
| }; | |
| /** | |
| * Creates regexp by tokens. | |
| */ | |
| const createRegExp = (...tokens) => { | |
| 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, 'gmu'); | |
| }; | |
| /** | |
| * Empty regexp that match only the empty string. | |
| */ | |
| const emptyRegExp = /^$/g; |