繁体   English   中英

如何编写用于递归计算Java解析器的递归while循环

[英]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的结果,因为令牌流再次为空,因此永远不会进入循环。

因此,这里出现的问题是您消耗了所有输入,而没有实际构建用于添加的树。 这样做的代码(即parsewhile循环)永远不会运行,因为由于parseTerm中的循环和第二次parse (由于丢弃了其结果),您已经在读所有令牌之前就已经读取了所有令牌)。

您的term语法规则不使用exp ,因此parseTerm不应调用parse 而且该规则也不是递归的,因此parseTerm不应包含循环。 parseTerm应该做的所有事情就是读取一个应该为文字的单个令牌,然后返回相应的Exp对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM