diff --git a/src/transformers/InlineParsersTransformer.js b/src/transformers/InlineParsersTransformer.js index 27aed75..9c8d28e 100644 --- a/src/transformers/InlineParsersTransformer.js +++ b/src/transformers/InlineParsersTransformer.js @@ -1,55 +1,24 @@ import AlternativeParser from "../parser/AlternativeParser.js" -import CapturingGroupParser from "../parser/CapturingGroupParser.js" +import ParentChildTransformer from "./ParentChildTransformer.js" import SequenceParser from "../parser/SequenceParser.js" -import Transformer from "./Transformer.js" -export default class InlineParsersTransformer extends Transformer { +/** @extends {ParentChildTransformer<[AlternativeParser, SequenceParser], [AlternativeParser, SequenceParser]>} */ +export default class InlineParsersTransformer extends ParentChildTransformer { - static #None = class { } + constructor() { + super([AlternativeParser, SequenceParser], [AlternativeParser, SequenceParser]) + } /** - * @template T - * @param {Parser} parser - * @return {Parser} + * @param {AlternativeParser[]> | SequenceParser[]>} parent + * @param {AlternativeParser[]> | SequenceParser[]>} child + * @returns {Parser[]} */ - doTransform(parser) { - /** - * @type {(new (...args: any) => AlternativeParser<[Parser, ...Parser[]]>) - * | (new (...args: any) => SequenceParser<[Parser, ...Parser[]]>)} - */ - const type = parser instanceof AlternativeParser ? AlternativeParser : SequenceParser - let changed = false - /** @type {Parser[]} */ - let children = parser.unwrap() - if (parser instanceof type) { - for (let i = 0; i < children.length; ++i) { - let current = children[i].actualParser([CapturingGroupParser]) - if (current instanceof type) { - children.splice( - i, - 1, - ...current.parsers.map(p => children[i].withActualParser(p, [CapturingGroupParser])) - ) - changed = true - --i - continue - } - const transformed = this.doTransform(current) - if (current != transformed) { - children[i] = children[i].withActualParser(transformed, [CapturingGroupParser]) - changed = true - } - } - } else { - children = children.map(child => { - const transformed = this.doTransform(child) - changed ||= child !== transformed - return transformed - }) - } - if (changed) { - return parser.wrap(...children) - } - return parser + doTransformChild(parent, child) { + return parent instanceof AlternativeParser && child instanceof AlternativeParser + || parent instanceof SequenceParser && child instanceof SequenceParser + ? child.unwrap() + : null } + } diff --git a/src/transformers/ParentChildTransformer.js b/src/transformers/ParentChildTransformer.js index 694ae06..076be8e 100644 --- a/src/transformers/ParentChildTransformer.js +++ b/src/transformers/ParentChildTransformer.js @@ -32,20 +32,33 @@ export default class ParentChildTransformer extends Transformer { for (let i = 0; i < children.length; ++i) { const current = children[i].actualParser(this.traverse, this.opaque) if (this.#childTypes.find(t => current instanceof t)) { - const replacement = this.doTransformParentChild( - /** @type {UnionFromArray} */(parser), - /** @type {UnionFromArray} */(current) + const newParent = this.doTransformParent( + /** @type {UnionFromArray} */(parser), + /** @type {UnionFromArray} */(current) ) - if (replacement !== parser) { - return this.doTransform(replacement) + if (newParent) { + return this.doTransform(newParent) } - } else { - const transformed = this.doTransform(current) - if (current !== transformed) { - children[i] = children[i].withActualParser(transformed, this.traverse, this.opaque) + const newChildren = this.doTransformChild( + /** @type {UnionFromArray} */(parser), + /** @type {UnionFromArray} */(current) + ) + if (newChildren) { + children.splice( + i, + 1, + ...newChildren.map(c => children[i].withActualParser(c, this.traverse, this.opaque)) + ) changed = true + --i + continue } } + const transformed = this.doTransform(current) + if (current !== transformed) { + children[i] = children[i].withActualParser(transformed, this.traverse, this.opaque) + changed = true + } } } else { children = children.map(child => { @@ -63,9 +76,18 @@ export default class ParentChildTransformer extends Transformer { /** * @param {UnionFromArray} parent * @param {UnionFromArray} child - * @returns {Parser} + * @returns {Parser?} + */ + doTransformParent(parent, child) { + return null + } + + /** + * @param {UnionFromArray} parent + * @param {UnionFromArray} child + * @returns {Parser[]?} */ - doTransformParentChild(parent, child) { - return parent + doTransformChild(parent, child) { + return null } } diff --git a/src/transformers/RemoveDiscardedMapTransformer.js b/src/transformers/RemoveDiscardedMapTransformer.js index 7c99d24..1b4f2b5 100644 --- a/src/transformers/RemoveDiscardedMapTransformer.js +++ b/src/transformers/RemoveDiscardedMapTransformer.js @@ -14,11 +14,20 @@ export default class RemoveDiscardedMapTransformer extends ParentChildTransforme * @param {LookaroundParser> | MapParser>} child * @returns {Parser} */ - doTransformParentChild(parent, child) { - if (parent instanceof LookaroundParser && child instanceof MapParser) { - return parent.wrap(parent.parser.withActualParser(child.parser, this.traverse, this.opaque)) - } else if (parent instanceof MapParser && child instanceof LookaroundParser) { + doTransformParent(parent, child) { + if (parent instanceof MapParser && child instanceof LookaroundParser) { return parent.parser.withActualParser(child, this.traverse, this.opaque) } } + + /** + * @param {LookaroundParser> | MapParser>} parent + * @param {LookaroundParser> | MapParser>} child + * @returns {Parser[]} + */ + doTransformChild(parent, child) { + if (parent instanceof LookaroundParser && child instanceof MapParser) { + return [child.parser] + } + } }