Java如何访问节点_提升精神如何从父节点访问子节点(叶子)

这篇博客探讨了如何利用Boost库来实现抽象语法树(AST)的遍历和表达式的评估。通过展示如何为二元运算符定义重载操作符,例如逻辑或(||)和等于(==),作者解释了如何以递归方式调用eval方法来获取子表达式值。博客还提到了使用模板和宏来简化代码,并提醒注意在处理非布尔表达式时可能需要的类型转换。此外,文章提及了在叶节点评估中处理变量值的待办事项以及对不同类型的值的支持。
摘要由CSDN通过智能技术生成

您是否查看了现有运营商的其他评估重载?您是否注意到他们如何获得操作数的值(实际上可能是子表达式)?

我以二进制或者为例:

bool operator()(const binop& b) const

{

return recurse(b.oper1) || recurse(b.oper2);

}

如您所见,它只是将 || 应用于两个操作数的值 . AST中没有找到该值[1] . 因此,我们将每个操作数视为一个表达式,并以递归方式在其上调用 eval 方法 .

private:

template

bool recurse(T const& v) const

{ return boost::apply_visitor(*this, v); }

所以,不知道你的其余语法,但假设你以与现有语法相同的方式扩展它:

bool operator()(const binop& u) const {

return recurse(b.oper1) == recurse(b.oper2);

}

会是对的 . 请注意,使用聪明的宏,您可以非常快速地完成:

struct eval : boost::static_visitor {

// terminal

value operator()(const var& v) const {

std::cout<

return true; // TODO get value from var

}

// unary operator

value operator()(const unop& u) const { return !recurse(u.oper1); }

/*

* binary operators

*/

#define EXPR_DEF_BINOP(tag, op) \

value operator()(const binop& u) const { \

return recurse(b.oper1) op recurse(b.oper2); \

}

EXPR_DEF_BINOP(op_and, &&)

EXPR_DEF_BINOP(op_equal, ==)

EXPR_DEF_BINOP(op_greater, >)

EXPR_DEF_BINOP(op_greater_equal, >=)

EXPR_DEF_BINOP(op_less,

EXPR_DEF_BINOP(op_less_equal, <=)

EXPR_DEF_BINOP(op_not_equal, !=)

EXPR_DEF_BINOP(op_or, ||)

#undef EXPR_DEF_BINOP

private:

template

value recurse(T const& v) const

{ return boost::apply_visitor(*this, v); }

};

还有一些说明:

我在叶节点评估函数中添加了一个TODO

我将类型更改为 value (来自 bool ) . 这是因为你的语法支持非布尔表达式,否则运算符 <= 和 >= 没有意义 . [2]因此你将拥有不同类型的值(也是):

using value = variant;

我会把剩下的留给你

[1]记住AST =抽象语法树:它是源的1:1表示 . ("half-exception"将是文字,但您仍需要告诉评估者如何使用文字的值 . )

[2]可以说

a

a>b 可能意味着 !b && a

a!=b 可能意味着 a XOR b

a==b 可能意味着 !(a XOR b)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设有一个对象数组 `Node[] nodes`,每个节点对象有一个 `parentId` 属性表示父节点 id,现在需要根据父子关系筛选出所有的父节点子节点。可以按照以下步骤实现: 1. 首先创建两个空的列表,分别存储父节点子节点。`List<Node> parents = new ArrayList<>();` `List<Node> children = new ArrayList<>();` 2. 遍历节点数组,如果节点的 `parentId` 为空,即为根节点,将其加入父节点列表。否则,将其加入子节点列表。`for (Node node : nodes) {if (node.getParentId() == null) {parents.add(node);} else {children.add(node);}}` 3. 遍历子节点列表,将每个子节点父节点加入父节点列表,如果该父节点已经在列表中,则不加入。`for (Node child : children) {Node parent = findParent(child, nodes);if (parent != null && !parents.contains(parent)) {parents.add(parent);}}` 4. 定义一个辅助方法 `findParent(Node child, Node[] nodes)`,用于查找子节点父节点。在节点数组中查找 `parentId` 与子节点的 `id` 相等的节点并返回。如果找不到,则返回 null。 5. 最终得到的父节点列表即为所有的根节点子节点列表即为所有的叶子节点。 下面是完整的代码示例: ```java List<Node> parents = new ArrayList<>(); List<Node> children = new ArrayList<>(); // 遍历节点数组,将节点分为父节点子节点 for (Node node : nodes) { if (node.getParentId() == null) { parents.add(node); } else { children.add(node); } } // 遍历子节点列表,将每个子节点父节点加入父节点列表 for (Node child : children) { Node parent = findParent(child, nodes); if (parent != null && !parents.contains(parent)) { parents.add(parent); } } // 查找子节点父节点 private Node findParent(Node child, Node[] nodes) { for (Node node : nodes) { if (child.getParentId().equals(node.getId())) { return node; } } return null; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值