# 算符优先算法

``````expression -> additive {% d => d[0] %}
additive "+" multiple {% d => d[0] + d[2] %}
| additive "-" multiple {% d => d[0] - d[2] %}
| multiple {% d => d[0] %}
multiple ->
multiple "*" factor {% d => d[0] * d[2] %}
| multiple "/" factor {% d => d[0] / d[2] %}
| factor {% d => d[0] %}

factor -> "(" additive ")" {% d => d[1] %}
| %number {% d => Number(d[0]) %}``````

``````class BinaryExpr{
constructor(left, op, right){
this.left = left
this.op = op
this.right = right
}
}

class OpPrecedenceParser{
constructor(lexer, precedenceMap){
this.lexer = lexer
this.precedenceMap = precedenceMap
}
expression(){
let right = this.factor()
let next;
while(next = this.nextOperator()){
right = this.doShift(right)
}
return right
}

doShift(left){
let right = this.factor()
let next;
while((next = this.nextOperator()) && this.rightIsExpr(op, next)){
right = this.doShift(right)
}
return new BinaryExpr(left, op, right)
}
nextOperator(){
const op = this.lexer.nextToken()
if(this.precedenceMap.get(op)) return op
return null
}
factor(){
if(this.lexer.nextToken() === "("){
this.token()
const exp = this.expression()
this.token()
return exp
} else {
}
}
token(){
}
rightIsExpr(op1, op2){
return this.precedenceMap.get(op1) < this.precedenceMap.get(op2)
}
}

class Lexer{
constructor(content){
this.currentIndex = 0
this.content = content || ""
this.tokens = []
}
peek(index){
return this.content[this.currentIndex + index]
}
nextToken(){
if(this.content[this.currentIndex])
return this.peek(0)
}
return this.content[this.currentIndex++]
}
}

function parse(expr){
const precedenceMap = new Map()
precedenceMap.set("+", 2)
precedenceMap.set("-", 2)
precedenceMap.set("*", 3)
precedenceMap.set("/", 3)
const lexer = new Lexer(expr)
const parser = new OpPrecedenceParser(lexer, precedenceMap)
const tree = parser.expression()
return tree
console.log(ast)
}
const ast = parse("3+4*5")
console.log(ast)``````

``````BinaryExpr {
left: '3',
op: '+',
right: BinaryExpr { left: '4', op: '*', right: '5' }
}``````

``````BinaryExpr {
left: BinaryExpr { left: '3', op: '+', right: '4' },
op: '*',
right: '5'
}``````

``````precedenceMap.set("<", 1)
precedenceMap.set(">", 1)``````

``````BinaryExpr {
left: BinaryExpr { left: '3', op: '+', right: '4' },
op: '>',
right: '5'
}``````

``````  doShift(left){
let right = this.factor()
let next;
while((next = this.nextOperator()) && this.rightIsExpr(op, next)){
right = this.doShift(right)
}
return new BinaryExpr(left, op, right)
}``````

• 《编程语言实现模式》
• 《两周自制脚本语言》

890 声望
69 粉丝
0 条评论