[英]How to write a recursive while loop for arimethic calculation java parser
我已经使用以下语法为算术计算解析器编写了代码
'exp':: =条款| 期限+ exp | 学期
术语:: =整数文字
我已经完成了仅包含整数文字的单个项的解析器,但是,我无法实现在字符串方程式中解析操作的目标。
在此应用程序中,我试图通过使用Tokenizer.hasNext()
方法检查是否存在下一个token
,并且该token
的类型是否为Token.Type.Add
然后返回带有当前文字项和操作的新Exp以及通过parse()
方法解析的下一个Exp。 我定义了各种类,例如Token(String token, Type type),Exp(Term) / Exp(Term,Op,Exp),Term(Lit),Lit(int)
Tokenizer.takeNext()
将获取下一个令牌并将其从当前令牌生成器缓冲区中删除。 我根本无法从给定的方程式解析运算符。
Parsing equation: 73 + 65
73=73
Parsing equation: 10 - 4
10=10
Parsing equation: 7 + 9 + 10
7=7
Parsing equation: 5 - 1
5=5
这是我从学校讲课中学到的一种通用方法,它不是作业问题。 任何帮助将不胜感激。
public class Token {
public enum Type {Unknown, Lit, Add, Minus, Multiply, Division};
private String _token = "";
private Type _type = Type.Unknown;
}
public enum Operation {
None (""),
Add ("+"),
Sub ("-"),
Mult ("*"),
Div ("/");
String op;
public class Exp {
Term _term = null;
Exp _exp = null;
Operation _op = null;
public Exp(Term term) {
_term = term;
_op = Operation.None;
}
public Exp(Term term, Operation op, Exp exp) {
_exp = exp;
_term = term;
_op = op;
}
public Exp parse(){
Exp term = parseTerm();
while(_tokenizer.hasNext()) {
Token token = _tokenizer.takeNext();
if(token.type() == Token.Type.Add) {
Operation op = Operation.Add;
_tokenizer.next();
Exp exp = parse();
term = new Exp(term._term,op,exp);
}
}
return term;
}
// <term> ::= <integer literal>
public Exp parseTerm(){
Exp exp = null;
String Lit = "";
while(_tokenizer.hasNext()) {
Token token = _tokenizer.takeNext();
if(token.type() == Token.Type.Lit)
Lit+=token.token();
else
parse();
}
Lit lit = new Lit(Integer.parseInt(Lit));
Term term = new Term(lit);
exp = new Exp(term);
return exp;
}
让我们通过输入73 + 65
来完成此操作:
您调用parse
,后者调用parseTerm
。 然后parseTerm
令牌。 对于第一个标记,它是一个文字,因此将其添加到Lit
(PS:变量名以大写字母开头不是很好的样式)。 然后读取+
令牌,并将其放入else
并调用parse
。 现在parse
再次调用parseLit
,它读取65
的文字。 令牌流现在为空,因此parseLit
返回。 因为令牌流仍然为空,所以还会返回parse
(请注意,从未输入过parse
中的循环)。
从parse
返回到parseLit
的值是文字表达式65
,但parseLit
从未实际使用该值。 它只是调用parse
并将结果丢弃。
因此,现在我们回到parseLit
的第一个调用中,并且parse
刚刚返回。 因此令牌流为空,我们退出循环。 Lit
的内容为“ 73”,因此这是对parseLit
调用返回的parseLit
。 现在,我们返回对parse
的第一个调用,该调用仅返回parseLit
的结果,因为令牌流再次为空,因此永远不会进入循环。
因此,这里出现的问题是您消耗了所有输入,而没有实际构建用于添加的树。 这样做的代码(即parse
的while
循环)永远不会运行,因为由于parseTerm
中的循环和第二次parse
(由于丢弃了其结果),您已经在读所有令牌之前就已经读取了所有令牌)。
您的term
语法规则不使用exp
,因此parseTerm
不应调用parse
。 而且该规则也不是递归的,因此parseTerm
不应包含循环。 parseTerm
应该做的所有事情就是读取一个应该为文字的单个令牌,然后返回相应的Exp
对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.