The function binOp runs once when run from expression and then becomes undefined when it is called by term and I just can't figure out why it is happening. sorry for the amount of code but I don't know where to look anymore. Also it is running in a nextjs localhost if that makes an difference
I get the following error:
TypeError: Cannot read properties of undefined (reading 'binOp')
class Parser {
tokens: Token[]
tokIdx: number
currentTok: Token
constructor(tokens: Token[]) {
this.tokens = tokens
this.tokIdx = -1
this.currentTok = new Token({type:"null"})
this.advance()
}
advance() {
this.tokIdx
if(this.tokIdx < this.tokens.length) {
this.currentTok = this.tokens[this.tokIdx]
}
return this.currentTok
}
binOp(func:any, ops:string[]) {
console.log("here")
let left: any = func()
while(this.currentTok.type == TT_MUL || this.currentTok.type == TT_DIV) {
let opTok = this.currentTok
this.advance()
let right = func()
left = new BinOpNode({leftNode:left, opTok:opTok, rightNode:right})
}
return left
}
parse() {
return this.expression()
}
factor() {
let tok: Token = this.currentTok
if(tok.type == TT_INT || tok.type == TT_FLOAT) {
this.advance()
return new NumberNode(tok)
}
}
term() {
return this.binOp(this.factor, [TT_MUL, TT_DIV])
}
expression() {
return this.binOp(this.term, [TT_PLUS, TT_MINUS])
}
}
CodePudding user response:
TypeError: Cannot read properties of undefined (reading 'binOp')
This error does not mean binOp
is undefined
. It means the object that is supposed to have that method is undefined
. This is a very important difference.
This line:
return this.binOp(this.term, [TT_PLUS, TT_MINUS])
Is not going to work. You can can't break off a class instances methods like this because the value of this
is lost.
The value of this
is set by how it's called. By default, when you call myObj.method()
then this
is set to myObj
inside the method
function.
All instances of a class share methods. So if you get a reference to method as a standalone function, there is no way to know what instance it came from. So this
cannot be the instance
that you expect.
So when you pass a method of class you either have to use an enclosing function:
return this.binOp(() => this.term(), [TT_PLUS, TT_MINUS])
Or bind the function before you pass it:
return this.binOp(this.term.bind(this), [TT_PLUS, TT_MINUS])