or

now it's time to do "or" properly.

this language bites "pasta" or "pizza" or "pie".

TRANSLATED:



let's recap...

we're making a term that matches any term you pass to it.

class OrTerm extends Term {
	constructor(terms) {
		super()
		this.terms = terms
	}
}

we give it a name.

class OrTerm extends Term {
	//...
	name() {
		return `${this.terms.map(term => term.name()).join(" or ")}`
	}
}

check is easy.

class OrTerm extends Term {
	//...
	check(text) {
		return this.terms.some(term => term.check(text))
	}
}

we bite the first term that matches.

class OrTerm extends Term {
	//...
	bite(text) {
		for (const term of this.terms) {
			const bite = term.bite(text)
			if (bite !== null) {
				return bite
			}
		}
		return null
	}
}

for travel, we first try the bite. if there's no bite, we travel all terms and use the longest travel.

class OrTerm extends Term {
	//...
	travel(text) {
		const bite = this.bite(text)
		if (bite !== null) {
			return bite
		}
		const travels = this.terms.map(term => term.travel(text))
		return travels.reduce((a, b) => a.length > b.length ? a : b)
	}
}

oh woah we haven't talked about emit much yet! but we need to emit the matching term.

class OrTerm extends Term {
	//...
	emit(text) {
		for (const term of this.terms) {
			const emit = term.emit(text)
			if (emit !== null) {
				return emit
			}
		}
		return null
	}
}

oh and for preview, we use the longest one.

class OrTerm extends Term {
	//...
	preview(text) {
		const previews = this.terms.map(term => term.preview(text))
		return previews.reduce((a, b) => a.length > b.length ? a : b)
	}
}

oh boy that was quite a lot of work! i think i might need to REFACTOR.

but either way it works

const pastaTerm = new StringTerm("pasta")
const pizzaTerm = new StringTerm("pizza")
const pieTerm = new StringTerm("pie")
const orTerm = new OrTerm([pastaTerm, pizzaTerm, pieTerm])

function translate(text) {
	return orTerm.translate(text)
}

back to the dream