tell-me-when
Version:
human relative date and time parser
122 lines (113 loc) • 2.87 kB
text/typescript
export class ParseNode {
name: string | undefined
from: number
to: number
children?: ParseNode[]
constructor(wrapped: ParseNode)
constructor(
name: string | undefined,
from: number,
to: number,
children?: ParseNode[]
)
constructor(
arg0: ParseNode | string | undefined,
from?: number,
to?: number,
children?: ParseNode[]
) {
if (arg0 instanceof ParseNode) {
this.name = arg0.name
this.from = arg0.from
this.to = arg0.to
this.children = arg0.children
} else {
if (from == null || to == null) {
throw new Error(
`from and to are required if first arg isn't a ParseNode`
)
}
this.name = arg0
this.from = from
this.to = to
this.children = children
}
}
static error(from: number, to: number = from) {
return new ParseNode('⚠', from, to)
}
static empty(index: number) {
return new ParseNode(undefined, index, index)
}
substringOf(input: string) {
return input.substring(this.from, this.to)
}
get isError() {
return this.name === '⚠'
}
get isEmpty() {
return this.from === this.to
}
find<N extends ParseNode>(
predicate:
| (abstract new (...args: any[]) => N)
| (new (...args: any[]) => N)
| ((node: ParseNode) => node is N)
): N | undefined
find(
predicate:
| string
| (abstract new (...args: any[]) => ParseNode)
| (new (...args: any[]) => ParseNode)
| ((node: ParseNode) => boolean)
): ParseNode | undefined
find(
predicate:
| string
| (abstract new (...args: any[]) => ParseNode)
| (new (...args: any[]) => ParseNode)
| ((node: ParseNode) => boolean)
): ParseNode | undefined {
for (const node of this.findAll(predicate)) {
return node
}
return undefined
}
findAll<N extends ParseNode>(
predicate:
| (abstract new (...args: any[]) => N)
| (new (...args: any[]) => N)
| ((node: ParseNode) => node is N)
): Iterable<N>
findAll(
predicate:
| string
| (abstract new (...args: any[]) => ParseNode)
| (new (...args: any[]) => ParseNode)
| ((node: ParseNode) => boolean)
): Iterable<ParseNode>
*findAll(
predicate:
| string
| (abstract new (...args: any[]) => ParseNode)
| (new (...args: any[]) => ParseNode)
| ((node: ParseNode) => boolean)
): Iterable<ParseNode> {
if (typeof predicate === 'string') {
yield* this.findAll((node) => node.name === predicate)
return
}
if (
predicate.prototype instanceof ParseNode
? this instanceof predicate
: (predicate as any)(this)
) {
yield this
}
if (this.children) {
for (const child of this.children) {
yield* child.findAll(predicate)
}
}
}
}