Leetcode [224] Basic Calculator 基于语法树的解法

简介: 通过生成语法树,解决表达式求值问题

代码

importjava.util.function.BooleanSupplier;
publicclassCalculator {
staticenumTokenType {
NUMBER,
PLUS_SIGN('+'),
MINUS_SIGN('-'),
LEFT_PARENTHESIS('('),
RIGHT_PARENTHESIS(')'),
END,
        ;
privatecharc;
TokenType(){
this.c=0;
        }
TokenType(charc){
this.c=c;
        }
staticTokenTypegetByChar(charc){
for(TokenTypetype : values()){
if(type.c!=0&&type.c==c){
returntype;
                }
            }
returnnull;
        }
    }
staticclassToken {
TokenTypetype;
Stringtext;
Token(){}
Token(TokenTypetype, Stringtext){
this.type=type;
this.text=text;
        }
    }
staticclassLexer {
Stringsource;
char[] chars;
intpos;
Tokennext;
Lexer(Stringsource){
this.source=source;
this.chars=source.toCharArray();
this.pos=0;
        }
TokengetNext(){
if(next!=null){
TokentheNext=next;
next=null;
returntheNext;
            }
while(pos<chars.length&&Character.isSpaceChar(chars[pos])){
pos++;
            }
if(pos==chars.length){
returnnewToken(TokenType.END, null);
            }
Tokentoken=newToken();
TokenTypetype;
if((type=TokenType.getByChar(chars[pos])) !=null){
token.type=type;
pos++;
            }else{
// 只能是一个数字 tokenintlen=1;
while(pos+len<chars.length&&Character.isDigit(chars[pos+len])){
len++;
                }
token.type=TokenType.NUMBER;
token.text=this.source.substring(pos, pos+len);
pos+=len;
            }
returntoken;
        }
TokenpeekNext(){
if(this.next!=null){
returnthis.next;
            }
this.next=getNext();
returnthis.next;
        }
booleanisEnd(){
returnpos==source.length();
        }
    }
staticclassParser {
Lexerlexer;
Parser(Lexerlexer){
this.lexer=lexer;
        }
ExpressionparseAll(){
returnparseArithmeticExpression(()->this.lexer.isEnd());
        }
ExpressionparseArithmeticExpression(BooleanSupplierendFunc){
ArithmeticExpressionexp=newArithmeticExpression();
ExpressionunaryExp=parseUnaryExpression();
exp.leftExpression=unaryExp;
while(!endFunc.getAsBoolean()){
Tokenoperator=lexer.getNext();
exp.arithmeticType=ArithmeticType.getFromToken(operator);
exp.rightExpression=parseUnaryExpression();
ArithmeticExpressionexpWrapper=newArithmeticExpression();
expWrapper.leftExpression=exp;
exp=expWrapper;
            }
returnexp;
        }
ExpressionoccurError(TokencurrentToken){
returnEmptyExpression.getSingleton();
        }
ExpressionparseUnaryExpression(){
Tokentoken=lexer.getNext();
switch(token.type){
caseEND:{
returnEmptyExpression.getSingleton();
                }
caseNUMBER:{
returnnewConstExpression(token.text);
                }
caseLEFT_PARENTHESIS:{
returnparseParenthesisExpression();
                }
caseMINUS_SIGN:{
returnnewUnaryMinusExpression(parseUnaryExpression());
                }
default:{
returnoccurError(token);
                }
            }
        }
ExpressionparseParenthesisExpression(){
Expressionexp=parseArithmeticExpression(()->this.lexer.peekNext().type==TokenType.RIGHT_PARENTHESIS);
this.lexer.getNext(); // pass 右括号returnexp;
        }
    }
staticinterfaceExpression {
intevaluate();
    }
staticclassEmptyExpressionimplementsExpression{
privatestaticfinalEmptyExpressionexp=newEmptyExpression();
privateEmptyExpression(){}
@Overridepublicintevaluate(){
return0;
        }
publicstaticEmptyExpressiongetSingleton(){
returnexp;
        }
    }
staticclassConstExpressionimplementsExpression{
privateStringtext;
ConstExpression(Stringtext){
this.text=text;
        }
@Overridepublicintevaluate() {
returnInteger.valueOf(this.text);
        }
    }
staticenumArithmeticType{
NO,
PLUS,
MINUS,
        ;
staticArithmeticTypegetFromToken(Tokentoken){
if(token.type==TokenType.PLUS_SIGN){
returnArithmeticType.PLUS;
            }
if(token.type==TokenType.MINUS_SIGN){
returnArithmeticType.MINUS;
            }
returnArithmeticType.NO;
        }
    }
staticclassArithmeticExpressionimplementsExpression {
privateExpressionleftExpression;
privateExpressionrightExpression;
privateArithmeticTypearithmeticType=ArithmeticType.NO;
@Overridepublicintevaluate() {
switch(arithmeticType){
casePLUS: {
returnleftExpression.evaluate() +rightExpression.evaluate();
                }
caseMINUS :{
returnleftExpression.evaluate() -rightExpression.evaluate();
                }
caseNO:{
returnleftExpression.evaluate();
                }
            }
return0;
        }
    }
staticclassUnaryMinusExpressionimplementsExpression {
privateExpressionoperand;
UnaryMinusExpression(Expressionoperand){
this.operand=operand;
        }
@Overridepublicintevaluate() {
return-operand.evaluate();
        }
    }
publicintevaluate(Stringsource){
Parserparser=newParser(newLexer(source));
returnparser.parseAll().evaluate();
    }
}
目录
相关文章
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
57 4
|
4月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
57 6
|
4月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
54 1
|
4月前
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
68 1
|
4月前
|
Python
【Leetcode刷题Python】538. 把二叉搜索树转换为累加树
LeetCode上538号问题"把二叉搜索树转换为累加树"的Python实现,使用反向中序遍历并记录节点值之和来更新每个节点的新值。
27 3
|
4月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
59 0
|
4月前
|
存储 算法 Java
LeetCode初级算法题:两数之和+斐波拉契数列多种java解法
LeetCode初级算法题:两数之和+斐波拉契数列多种java解法
49 0
|
6月前
|
存储 机器学习/深度学习 算法
皇后之战:揭秘N皇后问题的多维解法与智慧【python 力扣52题】
皇后之战:揭秘N皇后问题的多维解法与智慧【python 力扣52题】
|
6月前
|
存储 算法 数据可视化
力扣156题最全解法:如何上下翻转二叉树(递归与迭代方法详解,附图解)
力扣156题最全解法:如何上下翻转二叉树(递归与迭代方法详解,附图解)
|
6月前
|
存储 算法 数据可视化
深入解析力扣157题:用Read4高效读取N个字符(多种解法与详细图解)
深入解析力扣157题:用Read4高效读取N个字符(多种解法与详细图解)