Expression: minor type change & simplification

pre-fetching postfix simplifies code for 'lenient'
This commit is contained in:
sschuldenzucker
2020-12-06 22:58:08 +08:00
committed by Jun Yang
parent 6f2b24f7ca
commit ca18a579a1
+5 -14
View File
@@ -15,33 +15,24 @@ import { operatorImpls } from '../render/operator'
export class Expression { export class Expression {
private operands: any[] = [] private operands: any[] = []
private postfix: IterableIterator<Token> private postfix: Token[]
private lenient: boolean private lenient: boolean
public constructor (str: string, lenient: boolean = false) { public constructor (str: string, lenient: boolean = false) {
const tokenizer = new Tokenizer(str) const tokenizer = new Tokenizer(str)
this.postfix = toPostfix(tokenizer.readExpression()) this.postfix = [...toPostfix(tokenizer.readExpression())]
this.lenient = lenient this.lenient = lenient
} }
public evaluate (ctx: Context): any { public evaluate (ctx: Context): any {
// we manually loop over the iterator to tell if it's a single variable, for lenient. for (const token of this.postfix) {
let iterResult = this.postfix.next()
let isFirstToken = true
while (!iterResult.done) {
const token = iterResult.value
iterResult = this.postfix.next()
const isLastToken = iterResult.done
if (TypeGuards.isOperatorToken(token)) { if (TypeGuards.isOperatorToken(token)) {
const r = this.operands.pop() const r = this.operands.pop()
const l = this.operands.pop() const l = this.operands.pop()
const result = evalOperatorToken(token, l, r, ctx) const result = evalOperatorToken(token, l, r, ctx)
this.operands.push(result) this.operands.push(result)
} else { } else {
this.operands.push(evalToken(token, ctx, this.lenient && isFirstToken && isLastToken)) this.operands.push(evalToken(token, ctx, this.lenient && this.postfix.length == 1))
} }
isFirstToken = false
} }
return this.operands[0] return this.operands[0]
} }
@@ -58,7 +49,7 @@ export function evalToken (token: Token | undefined, ctx: Context, lenient: bool
try { try {
return ctx.get([variable, ...props]) return ctx.get([variable, ...props])
} catch (e) { } catch (e) {
// we catch the error thrown by Context.getFromScope() for undefined vars. // for lenient, we catch the error thrown by Context.getFromScope() for undefined vars.
// Alt, we could make this more robust by setting a flag or using a separate error class. // Alt, we could make this more robust by setting a flag or using a separate error class.
if (lenient && e instanceof TypeError && e.message.startsWith("undefined variable:")) { if (lenient && e instanceof TypeError && e.message.startsWith("undefined variable:")) {
return null return null