Skip to content

Commit

Permalink
Use only parent-child algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
barsdeveloper committed Nov 16, 2023
1 parent d0082b6 commit 6e0fa2e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 62 deletions.
61 changes: 15 additions & 46 deletions src/transformers/InlineParsersTransformer.js
Original file line number Diff line number Diff line change
@@ -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<T>} parser
* @return {Parser<T>}
* @param {AlternativeParser<Parser<any>[]> | SequenceParser<Parser<any>[]>} parent
* @param {AlternativeParser<Parser<any>[]> | SequenceParser<Parser<any>[]>} child
* @returns {Parser<any>[]}
*/
doTransform(parser) {
/**
* @type {(new (...args: any) => AlternativeParser<[Parser<any>, ...Parser<any>[]]>)
* | (new (...args: any) => SequenceParser<[Parser<any>, ...Parser<any>[]]>)}
*/
const type = parser instanceof AlternativeParser ? AlternativeParser : SequenceParser
let changed = false
/** @type {Parser<any>[]} */
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
}

}
46 changes: 34 additions & 12 deletions src/transformers/ParentChildTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<ParentTypes>} */(parser),
/** @type {UnionFromArray<ChildTypes>} */(current)
const newParent = this.doTransformParent(
/** @type {UnionFromArray<ParentTypes>} */(parser),
/** @type {UnionFromArray<ChildTypes>} */(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<ParentTypes>} */(parser),
/** @type {UnionFromArray<ChildTypes>} */(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 => {
Expand All @@ -63,9 +76,18 @@ export default class ParentChildTransformer extends Transformer {
/**
* @param {UnionFromArray<ParentTypes>} parent
* @param {UnionFromArray<ChildTypes>} child
* @returns {Parser<any>}
* @returns {Parser<any>?}
*/
doTransformParent(parent, child) {
return null
}

/**
* @param {UnionFromArray<ParentTypes>} parent
* @param {UnionFromArray<ChildTypes>} child
* @returns {Parser<any>[]?}
*/
doTransformParentChild(parent, child) {
return parent
doTransformChild(parent, child) {
return null
}
}
17 changes: 13 additions & 4 deletions src/transformers/RemoveDiscardedMapTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,20 @@ export default class RemoveDiscardedMapTransformer extends ParentChildTransforme
* @param {LookaroundParser<Parser<any>> | MapParser<Parser<any>>} child
* @returns {Parser<any>}
*/
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<Parser<any>> | MapParser<Parser<any>>} parent
* @param {LookaroundParser<Parser<any>> | MapParser<Parser<any>>} child
* @returns {Parser<any>[]}
*/
doTransformChild(parent, child) {
if (parent instanceof LookaroundParser && child instanceof MapParser) {
return [child.parser]
}
}
}

0 comments on commit 6e0fa2e

Please sign in to comment.