如何为算数计算 java 解析器编写递归 while 循环
How to write a recursive while loop for arimethic calculation java parser
我已经用以下语法编写了算术计算解析器的代码
'exp' ::= 术语 |术语 + exp |术语 - exp
term ::=整数文字
并且我已经完成了对仅包含整数字面量的单个项的解析,但是,我无法实现字符串方程中解析操作的目的。
在此应用程序中,我尝试使用 Tokenizer.hasNext()
方法检查是否存在下一个 token
,以及 token
的类型是否为 Token.Type.Add
然后 return 一个带有当前文字项和操作的新 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
returns。 parse
也returns因为token流还是空的(注意parse
里面的循环还没有进入)
从 parse
到 parseLit
的值 return 是文字表达式 65
,但 parseLit
从未实际使用该值。它只是调用 parse
并丢弃结果。
所以现在我们回到了 parseLit
的第一次调用,parse
刚刚 returned。所以令牌流是空的,我们退出循环。 Lit
的内容是“73”,因此这是对 parseLit
的调用 return 的内容。现在我们 return 第一次调用 parse
,它只是 return 是 parseLit
的结果,因为同样,令牌流是空的,所以循环永远不会进入.
所以这里出了什么问题是您消耗了所有输入而没有实际为加法构建树。用于执行此操作的代码(即 parse
中的 while
循环)永远不会运行,因为由于 [=12= 中的循环,您已经在进入循环之前读取了所有标记] 和对 parse
的第二次调用(您丢弃其结果)。
term
的语法规则不使用 exp
,因此 parseTerm
不应调用 parse
。而且该规则也不是递归的,因此 parseTerm
不应包含循环。 parseTerm
应该做的就是读取一个应该是文字的标记,然后 return 相应的 Exp
对象。
我已经用以下语法编写了算术计算解析器的代码
'exp' ::= 术语 |术语 + exp |术语 - exp
term ::=整数文字
并且我已经完成了对仅包含整数字面量的单个项的解析,但是,我无法实现字符串方程中解析操作的目的。
在此应用程序中,我尝试使用 Tokenizer.hasNext()
方法检查是否存在下一个 token
,以及 token
的类型是否为 Token.Type.Add
然后 return 一个带有当前文字项和操作的新 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
returns。 parse
也returns因为token流还是空的(注意parse
里面的循环还没有进入)
从 parse
到 parseLit
的值 return 是文字表达式 65
,但 parseLit
从未实际使用该值。它只是调用 parse
并丢弃结果。
所以现在我们回到了 parseLit
的第一次调用,parse
刚刚 returned。所以令牌流是空的,我们退出循环。 Lit
的内容是“73”,因此这是对 parseLit
的调用 return 的内容。现在我们 return 第一次调用 parse
,它只是 return 是 parseLit
的结果,因为同样,令牌流是空的,所以循环永远不会进入.
所以这里出了什么问题是您消耗了所有输入而没有实际为加法构建树。用于执行此操作的代码(即 parse
中的 while
循环)永远不会运行,因为由于 [=12= 中的循环,您已经在进入循环之前读取了所有标记] 和对 parse
的第二次调用(您丢弃其结果)。
term
的语法规则不使用 exp
,因此 parseTerm
不应调用 parse
。而且该规则也不是递归的,因此 parseTerm
不应包含循环。 parseTerm
应该做的就是读取一个应该是文字的标记,然后 return 相应的 Exp
对象。