···
-
export function initGenerator(_ids, _t) {
-
/** var id = state.index; */
-
class AssignIndexNode {
-
const member = t.memberExpression(ids.state, t.identifier('index'));
-
return t.variableDeclaration('var', [
-
t.variableDeclarator(this.id, member),
-
/** state.index = id; */
-
class RestoreIndexNode {
-
const expression = t.assignmentExpression(
-
t.memberExpression(ids.state, t.identifier('index')),
-
return t.expressionStatement(expression);
-
/** var id = node.length; */
-
class AssignLengthNode {
-
return t.variableDeclaration('var', [
-
t.memberExpression(ids.node, t.identifier('length'))
-
/** node.length = id; */
-
class RestoreLengthNode {
-
const expression = t.assignmentExpression(
-
t.memberExpression(ids.node, t.identifier('length')),
-
return t.expressionStatement(expression);
-
/** return; break id; */
-
const statement = this.id ? t.breakStatement(this.id) : t.returnStatement();
-
/** if (condition) { return; break id; } */
-
class AbortConditionNode {
-
constructor(condition, opts) {
-
this.condition = condition || null;
-
this.abort = opts.abort;
-
this.abortCondition = opts.abortCondition || null;
-
this.restoreIndex = opts.restoreIndex;
-
[this.restoreIndex.statement(), this.abort.statement()].filter(Boolean)
-
this.abortCondition ? this.abortCondition.statement() : null
-
/** Generates a full matcher for an expression */
-
constructor(ast, depth, opts) {
-
this.depth = depth || 0;
-
this.capturing = !!opts.capturing;
-
this.restoreIndex = opts.restoreIndex;
-
this.restoreLength = opts.restoreLength || null;
-
this.abortCondition = opts.abortCondition || null;
-
this.abort = opts.abort || null;
-
const execMatch = this.ast.expression;
-
const assignMatch = t.assignmentExpression('=', ids.match, execMatch);
-
const successNodes = t.blockStatement([
-
t.callExpression(t.memberExpression(ids.node, t.identifier('push')), [
-
const abortNodes = t.blockStatement(
-
this.abortCondition && this.abortCondition.statement(),
-
this.abort && this.restoreLength && this.restoreLength.statement(),
-
this.restoreIndex && this.restoreIndex.statement(),
-
this.abort && this.abort.statement(),
-
? t.ifStatement(t.unaryExpression('!', execMatch), abortNodes)
-
: t.ifStatement(assignMatch, successNodes, abortNodes),
-
/** Generates a full matcher for a group */
-
constructor(ast, depth, opts) {
-
this.depth = depth || 0;
-
if (ast.sequence.length === 1) {
-
return new ExpressionNode(ast.sequence[0], depth, opts);
-
const lengthId = t.identifier(`length_${depth}`);
-
capturing: !!opts.capturing && !!ast.capturing,
-
this.assignLength = null;
-
if (!childOpts.restoreLength && childOpts.capturing) {
-
this.assignLength = new AssignLengthNode(lengthId);
-
childOpts.restoreLength = new RestoreLengthNode(lengthId);
-
this.alternation = new AlternationNode(ast.sequence, depth + 1, childOpts);
-
this.assignLength && this.assignLength.statement(),
-
...this.alternation.statements(),
-
/** Generates looping logic around another group or expression matcher */
-
constructor(ast, depth, opts) {
-
const { quantifier } = ast;
-
this.depth = depth || 0;
-
const invertId = t.identifier(`invert_${this.depth}`);
-
const loopId = t.identifier(`loop_${this.depth}`);
-
const iterId = t.identifier(`iter_${this.depth}`);
-
const indexId = t.identifier(`index_${this.depth}`);
-
const ChildNode = ast.type === 'group' ? GroupNode : ExpressionNode;
-
const childOpts = { ...opts };
-
this.assignIndex = null;
-
this.restoreIndex = null;
-
if (ast.type === 'group' && !!ast.lookahead) {
-
this.restoreIndex = new RestoreIndexNode(indexId);
-
this.assignIndex = new AssignIndexNode(indexId);
-
if (ast.type === 'group' && ast.lookahead === 'negative') {
-
childOpts.abort = new AbortNode(invertId);
-
childOpts.restoreIndex = this.restoreIndex;
-
this.restoreIndex = opts.restoreIndex;
-
this.blockId = invertId;
-
this.abort = opts.abort;
-
if (quantifier && !quantifier.singular && quantifier.required) {
-
childOpts.abortCondition = new AbortConditionNode(iterId, {
-
restoreIndex: new RestoreIndexNode(indexId),
-
abort: new AbortNode(loopId),
-
} else if (quantifier && !quantifier.singular) {
-
childOpts.restoreLength = null;
-
childOpts.restoreIndex = new RestoreIndexNode(indexId);
-
childOpts.abort = new AbortNode(loopId);
-
childOpts.abortCondition = null;
-
} else if (quantifier && !quantifier.required) {
-
childOpts.restoreIndex = new RestoreIndexNode(indexId);
-
childOpts.abortCondition = null;
-
childOpts.abort = null;
-
this.childNode = new ChildNode(ast, depth, childOpts);
-
const { quantifier } = this.ast;
-
const loopId = t.identifier(`loop_${this.depth}`);
-
const iterId = t.identifier(`iter_${this.depth}`);
-
const indexId = t.identifier(`index_${this.depth}`);
-
const assignIndex = new AssignIndexNode(indexId);
-
if (quantifier && !quantifier.singular && quantifier.required) {
-
t.variableDeclaration('var', [
-
t.variableDeclarator(iterId, t.numericLiteral(0)),
-
t.booleanLiteral(true),
-
t.updateExpression('++', iterId),
-
assignIndex.statement(),
-
...this.childNode.statements(),
-
} else if (quantifier && !quantifier.singular) {
-
t.booleanLiteral(true),
-
assignIndex.statement(),
-
...this.childNode.statements(),
-
} else if (quantifier && !quantifier.required) {
-
statements = [assignIndex.statement(), ...this.childNode.statements()];
-
statements = this.childNode.statements();
-
if (this.blockId && this.assignIndex && this.restoreIndex) {
-
this.assignIndex.statement(),
-
this.restoreIndex.statement(),
-
this.abort.statement(),
-
} else if (this.assignIndex && this.restoreIndex) {
-
statements.unshift(this.assignIndex.statement());
-
statements.push(this.restoreIndex.statement());
-
/** Generates a matcher of a sequence of sub-matchers for a single sequence */
-
constructor(ast, depth, opts) {
-
this.depth = depth || 0;
-
const indexId = t.identifier(`index_${depth}`);
-
const blockId = t.identifier(`block_${this.depth}`);
-
this.returnStatement = opts.returnStatement;
-
this.assignIndex = ast.alternation ? new AssignIndexNode(indexId) : null;
-
this.quantifiers = ast.sequence.map((childAst) => {
-
return new QuantifierNode(childAst, depth, {
-
restoreIndex: ast.alternation
-
? new RestoreIndexNode(indexId)
-
abortCondition: ast.alternation ? null : opts.abortCondition,
-
abort: ast.alternation ? new AbortNode(blockId) : opts.abort,
-
const blockId = t.identifier(`block_${this.depth}`);
-
const alternationId = t.identifier(`alternation_${this.depth}`);
-
const statements = this.quantifiers.reduce((block, node) => {
-
block.push(...node.statements());
-
if (!this.ast.alternation) {
-
this.depth === 0 ? this.returnStatement : t.breakStatement(alternationId);
-
this.assignIndex && this.assignIndex.statement(),
-
/** Generates matchers for sequences with (or without) alternations */
-
class AlternationNode {
-
constructor(ast, depth, opts) {
-
this.depth = depth || 0;
-
for (let current = ast; current; current = current.alternation) {
-
this.sequences.push(new SequenceNode(current, depth, opts));
-
if (this.sequences.length === 1) {
-
return this.sequences[0].statements();
-
for (let i = 0; i < this.sequences.length; i++) {
-
statements.push(...this.sequences[i].statements());
-
if (this.depth === 0) {
-
const alternationId = t.identifier(`alternation_${this.depth}`);
-
return [t.labeledStatement(alternationId, t.blockStatement(statements))];
-
export class RootNode {
-
constructor(ast, nameNode, transformNode) {
-
const indexId = t.identifier('last_index');
-
const node = t.callExpression(ids.tag, [ids.node, nameNode]);
-
this.returnStatement = t.returnStatement(
-
transformNode ? t.callExpression(transformNode, [node]) : node
-
this.assignIndex = new AssignIndexNode(indexId);
-
this.node = new AlternationNode(ast, 0, {
-
returnStatement: this.returnStatement,
-
restoreIndex: new RestoreIndexNode(indexId, true),
-
abort: new AbortNode(),
-
this.assignIndex.statement(),
-
t.variableDeclaration('var', [
-
t.variableDeclarator(ids.match),
-
t.variableDeclarator(ids.node, t.arrayExpression()),
-
...this.node.statements(),