加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 在复合结构上使用解释器模式

发布时间:2020-12-15 00:06:56 所属栏目:Java 来源:网络整理
导读:我被要求使用Composite,Recursive Descendent Parser和Interpreter进行表达式求值. 这是语法: cond → termb [OR termb]*termb→factb[AND factb]*factb→expr RELOP expr | NOT factb | OPAR cond CPARexpr → [PLUS | MINUS] term [(PLUS term) | (MINUS
我被要求使用Composite,Recursive Descendent Parser和Interpreter进行表达式求值.

这是语法:

<cond> → <termb> [OR <termb>]*
<termb>→<factb>[AND <factb>]*
<factb>→<expr> RELOP <expr> | NOT <factb> | OPAR <cond> CPAR
<expr> → [PLUS | MINUS] <term> [(PLUS <term>) | (MINUS <term>)]*
<term> → <termp> [(MULT <termp>) | (DIV <termp>) | (REM <termp>)]*
<termp> → <fact> [POWER <fact>]*
<fact> → ID | NUM | OPAR1 <expr> CPAR1
----TERMINALS----
ID → ("A" | ... | "Z" | "a" | ...| "z") [("A"| ... | "Z" | "a" | ...| "z" | "0" | ... | "9")]*
NUM → ("0" | ... | "9") [("0" | ... | "9")]*
OPAR → "("
CPAR → ")"
OPAR1 → "["
CPAR1 → "]"
RELOP → EQ | NEQ | GT | GE | LT | LE
EQ → "= ="
NEQ → "!="
GT → ">"
GE → ">="
LT → "<"
LE → "<="
POWER → "^"
DIV → "/"
REM → "%"
MULT → "*"
MINUS → "?"
PLUS → "+"
AND → “and” or “&&”
OR → “or” or “||”
NOT → “not” or “!”

作业是:

The goal of the project,based on Composite,Recursive Builder and
Interpreter,is to get a conditional expression,do a syntax analysis
and build its composite tree. Starting from the tree,you’ve got to
evaluate the result of the condition,based on an external context
(read from a properties file) that contains the value of the internal
variables

现在,我注意到的第一件事是,Interpreter使用了一个Composite结构,所以使用evaluate(:Context)方法扩展我的Composite结构似乎是个好主意.

我问过,但是我被告知这不是做这个任务的方式.
似乎我已经建立了解释器树,从复合树开始(对我而言,这是非常无聊的,因为我已经有一棵树可以使用了!).

所以我使用复合递归生成器构建了我的树,它识别输入,它构建树没有任何种类的问题.

但问题是:我如何将解释器应用于我的结构?

这是我的课程图(有些是意大利语,但这是很容易理解的)

如果我的意思是正确的,口译员会为每个语法规则使用一个类,所以我必须做一个cond类,然后是一个termb等等.

但是我可以将它们链接到我的组合?

解决方法

不知道为什么你被告知不要使用相同的树结构.我想我会在我的表达式界面中添加一个evaluate()方法.对于我,这说得通.一个表达应该知道如何评估自己.

我会说你当前的表达式界面暴露太多(如操作数).作为表达的客户,我只需要1)调用它,2)读取结果,我猜也许3)打印.其实,我宁愿使用toString()直接打印.

你可能已经注意到,但并不是所有的表达式都需要2个操作数(例如NOT或NEGATE).这已经与您的界面产生了一些差异.我会简化为:

public interface Expression {
   int evaluate();
 }

然后,您的每个操作和终端都知道如何评估自身(并将其自身转换为字符串).

所以我可以有具体的操作,如:

public class Terminal implements Expression {
   private final int value;

   public Terminal(int value) { this.value = value; }

   public int evaluate() { return value; }

   public String toString() { return String.valueOf(value); }
 }

 public class Add implements Expression {
   private final Expression left;
   private final Expression right;

   public Add(Expression left,Expression right) {
     this.left = left;
     this.right = right;
   }

   public String toString() {
     return left.toString() + " + " + right.toString();
   }

   // leave the rest for you
 }

现在我可以很容易地构建树

Expression expr = new Add(new Terminal(1),new Subtract(new Terminal(2),new Terminal(3)));

int result = expr.evaluate();
System.out.print(expr.toString() + " = " + result);

我甚至不需要直接访问各个操作数.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读