or

we can now start to make terms that do all sorts of funky things.

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

TRANSLATED:



this is done by making an "or" term.

the "or" term takes two terms as ARGUMENTS. it checks if either term matches.

class OrTerm extends Term {
	constructor(term1, term2) {
		super()
		this.term1 = term1
		this.term2 = term2
	}
	//...
}

then we need to IMPLEMENT all of the different term methods! as always, check is the EASIEST.

class OrTerm extends Term {
	//...
	check(text) {
		return this.term1.check(text) || this.term2.check(text)
	}
}

bite is easy too. we try the first term first. if it doesn't work, we try the second one.

class OrTerm extends Term {
	//...
	bite(text) {
		if (this.term1.check(text)) {
			return this.term1.bite(text)
		}
		
		if (this.term2.check(text)) {
			return this.term2.bite(text)
		}

		return null
	}
}

travel is similar, but if nothing matches, we use the longest travel.

class OrTerm extends Term {
	//...
	travel(text) {
		if (this.term1.check(text)) {
			return this.term1.bite(text)
		}
		if (this.term2.check(text)) {
			return this.term2.bite(text)
		}

		const travel1 = this.term1.travel(text)
		const travel2 = this.term2.travel(text)
		return travel1.length > travel2.length ? travel1 : travel2
	}
}

there's a sneaky trick for tail. you can [just] get the bite and then take what's left over.

class OrTerm extends Term {
	//...
	tail(text) {
		const bite = this.bite(text)
		if (bite === null) return null
		return text.slice(bite.length)
	}
}

we can't give a helpful error message yet.

class OrTerm extends Term {
	//...
	error(text) {
		if (this.check(text)) {
			return null
		}
		return `FRIGHTENING error: expected one of two terms but found '${text}'!`
	}
}

back to the dream