如何基于给定四则运算语法规则在Java中构建AST抽象语法树
递归下降法构建AST实现思路
你的语法规则天然按照运算符优先级分层,非常适合用递归下降解析器实现,具体实现思路如下:
第一步:重构词法分析模块
你当前的词法分析仅输出打印token,需要先改造为结构化输出:
- 定义
Token类,包含两个属性:type(枚举类型,可选值为NUMBER/IDENTIFIER/SYMBOL)、value(存储token实际内容,例如3、*、x) - 将原打印token的逻辑改为:按生成顺序把token存入
Queue<Token>队列,后续解析器直接从队列头部取token即可 - 注意如果存在多字符符号(例如你正则里的
:=),要保证最长匹配原则,避免把:=拆成:和=两个符号
第二步:定义AST节点结构
可以定义抽象父类AstNode,再派生三类具体节点:
NumberNode:对应数字常量,存储整型/浮点型数值IdentifierNode:对应标识符,存储变量名BinaryOpNode:对应二元运算,存储运算符、左子节点、右子节点
第三步:按语法规则实现递归解析函数
你的语法已经按运算符优先级从低到高分层(加法<减法<除法<乘法<括号/常量/变量),每个层级对应一个解析函数,逻辑完全对齐语法规则:
语法规则回顾:
expression ::= term { + term }
term ::= factor { - factor }
factor ::= piece { / piece }
piece ::= element { * element }
element ::= ( expression ) | NUMBER | IDENTIFIER
每个解析函数的统一逻辑:先解析当前层级的第一个子节点,循环判断下一个token是否为当前层级对应的运算符,是则吃掉运算符、解析下一个子节点,生成二元运算节点作为新的当前节点,直到没有匹配的运算符为止。
示例代码结构参考:
// 解析加法层级(最顶层) AstNode parseExpression() { AstNode left = parseTerm(); // 循环处理后续所有+运算符 while (peekToken().getType() == SYMBOL && peekToken().getValue().equals("+")) { consumeToken(); // 取出当前+运算符token AstNode right = parseTerm(); left = new BinaryOpNode("+", left, right); } return left; }
其他层级的解析函数逻辑完全对应:
parseTerm():先调用parseFactor(),循环处理-运算符parseFactor():先调用parsePiece(),循环处理/运算符parsePiece():先调用parseElement(),循环处理*运算符parseElement():根据当前token类型处理:- 如果是
(:吃掉(,调用parseExpression(),再吃掉),返回解析得到的节点 - 如果是
NUMBER:生成NumberNode返回,吃掉当前token - 如果是
IDENTIFIER:生成IdentifierNode返回,吃掉当前token
- 如果是
第四步:入口调用
整个解析的入口直接调用parseExpression(),返回的根节点就是完整的AST结构,和你给出的期望结构完全匹配。
内容的提问来源于stack exchange,提问作者Wesley
相关产品推荐
相关产品推荐

