Mirror: The magical sticky regex-based parser generator 🧙

Simplify quantifier type in parser AST

+5 -6
src/codegen.js
···
const _match = 'match';
const _node = 'node';
-
export function js(/* arguments */) {
+
function js(/* arguments */) {
let body = arguments[0][0];
for (let i = 1; i < arguments.length; i++)
-
body = body + arguments[i] + (arguments[0][i] || '');
+
body = body + arguments[i] + arguments[0][i];
return body.trim();
}
···
}
let child;
-
if (ast.quantifier && !ast.quantifier.singular && ast.quantifier.required) {
+
if (ast.quantifier === 'repeating') {
child = astRepeating(ast, depth, opts);
-
} else if (ast.quantifier && !ast.quantifier.singular)
+
} else if (ast.quantifier === 'multiple')
child = astMultiple(ast, depth, opts);
-
else if (ast.quantifier && !ast.quantifier.required)
-
child = astOptional(ast, depth, opts);
+
else if (ast.quantifier === 'optional') child = astOptional(ast, depth, opts);
else child = astChild(ast, depth, opts);
if (ast.lookahead === 'negative') {
+1 -2
src/core.js
···
-
import { js, astRoot } from './codegen';
+
import { astRoot } from './codegen';
import { parse as parseDSL } from './parser';
const isStickySupported = typeof /./g.sticky === 'boolean';
export const _pattern = (input) => {
if (typeof input === 'function') return input;
-
const source = typeof input !== 'string' ? input.source : input;
return isStickySupported
? new RegExp(source, 'y')
+3 -10
src/parser.js
···
(lastMatch =
currentSequence.sequence[currentSequence.sequence.length - 1])
) {
-
if (lastMatch.type === 'group' && lastMatch.lookahead) {
-
throw new SyntaxError('Unexpected quantifier on lookahead group');
-
}
-
-
lastMatch.quantifier = {
-
type: 'quantifier',
-
required: char === '+',
-
singular: char === '?',
-
};
-
+
lastMatch.quantifier = 'optional';
+
if (char === '+') lastMatch.quantifier = 'repeating';
+
if (char === '*') lastMatch.quantifier = 'multiple';
continue;
}
+5 -31
src/parser.test.js
···
ast = parseTag`${1}?`;
expect(ast).toHaveProperty('sequence.0.type', 'expression');
-
expect(ast).toHaveProperty('sequence.0.quantifier', {
-
type: 'quantifier',
-
required: false,
-
singular: true,
-
});
+
expect(ast).toHaveProperty('sequence.0.quantifier', 'optional');
ast = parseTag`${1}+`;
expect(ast).toHaveProperty('sequence.0.type', 'expression');
-
expect(ast).toHaveProperty('sequence.0.quantifier', {
-
type: 'quantifier',
-
required: true,
-
singular: false,
-
});
+
expect(ast).toHaveProperty('sequence.0.quantifier', 'repeating');
ast = parseTag`${1}*`;
expect(ast).toHaveProperty('sequence.0.type', 'expression');
-
expect(ast).toHaveProperty('sequence.0.quantifier', {
-
type: 'quantifier',
-
required: false,
-
singular: false,
-
});
+
expect(ast).toHaveProperty('sequence.0.quantifier', 'multiple');
});
it('supports top-level alternations', () => {
···
expect(ast).toHaveProperty('alternation.sequence.0.expression', 2);
ast = parseTag`${1}? | ${2}?`;
-
expect(ast).toHaveProperty('sequence.0.quantifier.type', 'quantifier');
-
expect(ast).toHaveProperty(
-
'alternation.sequence.0.quantifier.type',
-
'quantifier'
-
);
+
expect(ast).toHaveProperty('sequence.0.quantifier', 'optional');
});
it('supports groups with quantifiers', () => {
···
ast = parseTag`(${1} ${2}?)?`;
expect(ast).toHaveProperty('sequence.length', 1);
expect(ast).toHaveProperty('sequence.0.type', 'group');
-
expect(ast).toHaveProperty('sequence.0.quantifier.type', 'quantifier');
+
expect(ast).toHaveProperty('sequence.0.quantifier', 'optional');
expect(ast).toHaveProperty('sequence.0.sequence.sequence.0.quantifier', null);
-
expect(ast).toHaveProperty(
-
'sequence.0.sequence.sequence.1.quantifier.type',
-
'quantifier'
-
);
});
it('supports non-capturing groups', () => {
···
expect(ast).toHaveProperty('sequence.0.capturing', false);
expect(ast).toHaveProperty('sequence.0.lookahead', 'negative');
expect(ast).toHaveProperty('sequence.0.sequence.sequence.length', 1);
-
});
-
-
it('throws when a quantifier is combined with a lookahead', () => {
-
expect(() => parseTag`(?! ${1})+`).toThrow();
-
expect(() => parseTag`(?! ${1})?`).toThrow();
-
expect(() => parseTag`(?! ${1})*`).toThrow();
});
it('supports groups with alternates', () => {