parseMaybeConditional
- 调用
parseExprOps方法获取单个表达式
- 调用
this.eat(tt.question), 如果后面接了问号, 则此时创建新node, 并将node.test设置为前面解析出来的node
- 然后依次调用
parseMaybeAssign得到接下来的2个表达式内容. 返回为NodeTypes.ConditionalExpression
- 如果没有读到问号, 则此时直接返回为
parseExprOps解析到的表达式
pp.parseMaybeConditional = function(forInit, refDestructuringErrors) {
let startPos = this.start, startLoc = this.startLoc
let expr = this.parseExprOps(forInit, refDestructuringErrors)
if (this.checkExpressionErrors(refDestructuringErrors)) return expr
if (this.eat(tt.question)) {
let node = this.startNodeAt(startPos, startLoc)
node.test = expr
node.consequent = this.parseMaybeAssign()
this.expect(tt.colon)
node.alternate = this.parseMaybeAssign(forInit)
return this.finishNode(node, NodeTypes.ConditionalExpression)
}
return expr
}
parseExprOps
- 首先调用
parseMaybeUnary调出单个变量
- 判断expr.type === "ArrowFunctionExpression", 如果是, 则调用
parseExprOp继续读出表达式运算
pp.parseExprOps = function(forInit, refDestructuringErrors) {
let startPos = this.start, startLoc = this.startLoc
let expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit)
if (this.checkExpressionErrors(refDestructuringErrors)) return expr
return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit)
}
parseMaybeUnary
- 首先判断是否有await上下文并且在async内, 如果是, 则调用
parseAwait解析表达式
- 判断是否存在prefix, 这里是指++/--或者typeof, delete, 如果是, 则新建node, 并且将node.operator设置为操作符, 设置prefix为true, 并且递归调用
parseMaybeUnary解析出后面的内容.
- 如果是++/--, 则检查一下合法性.
- 如果读出来是单个变量名, 并且运算符为delete, 则报错.
- 如果读出来是私有变量, 并且运算符为delete, 则报错. 否则返回node
- 如果sawUnary为false, 并且为私有变量, 则此时调用
parsePrivateIdent解析为私有变量.
- 如果以上都不是, 则此时调用
parseExprSubscripts解析子表达式, 然后判断是否有后缀运算符, 如果有, 则创建新的节点并设置为UnaryExpression
- 最后, 检查是否存在幂运算符
**, 如果有则创建一个新的 AST 节点,类型为 BinaryExpression,并返回该节点
pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) {
let startPos = this.start, startLoc = this.startLoc, expr
if (this.isContextual("await") && this.canAwait) {
expr = this.parseAwait(forInit)
sawUnary = true
} else if (this.type.prefix) {
let node = this.startNode(), update = this.type === tt.incDec
node.operator = this.value
node.prefix = true
this.next()
node.argument = this.parseMaybeUnary(null, true, update, forInit)
this.checkExpressionErrors(refDestructuringErrors, true)
if (update) this.checkLValSimple(node.argument)
else if (this.strict && node.operator === "delete" &&
node.argument.type === "Identifier")
this.raiseRecoverable(node.start, "Deleting local variable in strict mode")
else if (node.operator === "delete" && isPrivateFieldAccess(node.argument))
this.raiseRecoverable(node.start, "Private fields can not be deleted")
else sawUnary = true
expr = this.finishNode(node, update ? nt.UpdateExpression : nt.UnaryExpression)
} else if (!sawUnary && this.type === tt.privateId) {
if (forInit || this.privateNameStack.length === 0) this.unexpected()
expr = this.parsePrivateIdent()
if (this.type !== tt._in) this.unexpected()
} else {
expr = this.parseExprSubscripts(refDestructuringErrors, forInit)
if (this.checkExpressionErrors(refDestructuringErrors)) return expr
while (this.type.postfix && !this.canInsertSemicolon()) {
let node = this.startNodeAt(startPos, startLoc)
node.operator = this.value
node.prefix = false
node.argument = expr
this.checkLValSimple(expr)
this.next()
expr = this.finishNode(node, nt.UnaryExpression)
}
}
if (!incDec && this.eat(tt.starstar)) {
if (sawUnary)
this.unexpected(this.lastTokStart)
else
return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false)
} else {
return expr
}
}
parseAwait
- 调用
parseMaybeUnary解析出对应的表达式
pp.parseAwait = function(forInit) {
if (!this.awaitPos) this.awaitPos = this.start
let node = this.startNode()
this.next()
node.argument = this.parseMaybeUnary(null, true, false, forInit)
return this.finishNode(node, NodeTypes.AwaitExpression)
}
parseExprSubscripts
- 首先调用
parseExprAtom解析表达式的初始部分
- 其次判断是否箭头函数, 如果是, 则直接返回
- 如果不是箭头函数, 则调用
parseSubscripts进行解析
pp.parseExprSubscripts = function (refDestructuringErrors, forInit) {
let startPos = this.start, startLoc = this.startLoc
let expr = this.parseExprAtom(refDestructuringErrors, forInit)
if (expr.type === NodeTypes.ArrowFunctionExpression && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
return expr
let result = this.parseSubscripts(expr, startPos, startLoc, false, forInit)
if (refDestructuringErrors && result.type === NodeTypes.MemberExpression) {
if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1
if (refDestructuringErrors.parenthesizedBind >= result.start) refDestructuringErrors.parenthesizedBind = -1
if (refDestructuringErrors.trailingComma >= result.start) refDestructuringErrors.trailingComma = -1
}
return result
}