Skip to content

Instantly share code, notes, and snippets.

@Etheresk
Created October 29, 2023 08:38
Show Gist options
  • Save Etheresk/e2cddf413ba8d37d0041d96214032f4e to your computer and use it in GitHub Desktop.
Save Etheresk/e2cddf413ba8d37d0041d96214032f4e to your computer and use it in GitHub Desktop.
Simple arithmetic parser without error recovery
export class ArithmeticParser {
private readonly input: string
private pos: number
public constructor(input: string) {
this.input = input
this.pos = 0
}
private _match(regexp: RegExp): string | null {
while (/\s+/.test(this.input[this.pos])) this.pos++
const match = this.input.slice(this.pos).match(regexp)
if (match && match.index === 0) {
this.pos += match[0].length
return match[0]
}
return null
}
private _number(): number | null {
const numStr = this._match(/^(0|[1-9](\d+)?)/)
return numStr ? Number.parseFloat(numStr) : null
}
private _factor(): number | null {
const num = this._number()
if (num !== null) return num
if (this._match(/^\(/)) {
const expr = this._expression()
if (this._match(/^\)/)) return expr
}
return null
}
private _power(): number | null {
let base = this._factor() ?? 0
while (true) {
const op = this._match(/^\^/)
if (op === null) break
const exponent = this._factor()
if (exponent === null) return null
base **= exponent
}
return base
}
private _term(): number | null {
let left = this._power() ?? 0
while (true) {
const op = this._match(/^[*/]/)
if (op === null) break
const right = this._power()
if (right === null) return null
if (op === '*') left *= right
else left /= right
}
return left
}
private _expression(): number | null {
let left = this._term() ?? 0
while (true) {
const op = this._match(/^[+-]/)
if (op === null) break
const right = this._term()
if (right === null) return null
if (op === '+') left += right
else left -= right
}
return left
}
public parse(): number | null {
const result = this._expression()
if (result !== null && this.pos === this.input.length) return result
return null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment