Java:了解递归下降解析器实现

时间:2017-10-23 13:41:25

标签: java parsing recursion recursive-descent

我们说我们有一个简单的语法:

  1. Program :: = Expression
  2. Expression :: = Number
  3. :: = - (表达,表达)
  4. 用这个表达式: - ( - (8,3)4)
    返回1.

    我的令牌流(我将parens和逗号拼接出来)看起来像这样 (减号 - )
    (减号 - )
    (INTEGER 8)
    (整数3)
    (整数4)

    因此AST看起来如此 。 。 -
    。 - 。 4
    8..3

    我的问题是,关于语法的递归性质。如果差异表达式有2个计算表达式,那么java示例如何工作。

    我尝试将表达式传递给类构造函数,如下所示:

    public class DiffExp implements LetLangExp {
      LetLangExp left, right;
    
      public DiffExp(LetLangExp l, LetLangExp r) {
        left = l;
        right = r;
        eval();
      }
    }
    

    这适用于 - (数字,数字)的差异表达式,但递归地它不会,因为我似乎无法绕过解析它的递归本质。我坚持这个例子并且我已经在线查看,但我似乎无法将这种类型的语法变得模糊不清。

    本质上我如何实现递归处理的差异表达式,它可以将差值表达式作为操作数并相应地计算?

    编辑:根据Markspace的请求,我试图为解析树构建节点结构。这是我现在的课程。

    class ExprNode{
    String c;
    static String operator;
    static ExprNode operand1;
    static ExprNode operand2;
    
    public ExprNode(String num){
        c = num;
        operand1 = operand2 = null;
    }
    
    public static void Expr(String op, ExprNode e1, ExprNode e2){
        operator = op;
        operand1 = e1;
        operand2 = e2;
    }
    }
    

2 个答案:

答案 0 :(得分:0)

您应该从语法中为每个规则创建方法,例如:

parseProgram(String program) {
  return parseExpression(program)
}

parseExpression(String expression) {

  if ( isNumber(expression) ) {
    return parseNumber(expression);
  } else 
  if ( isSignedExpression(expression) ) {
    String left = getLeftExpression(expression);
    String right = getRightExpression(expression);

    return parseExpression(left) - parseExpression(right);
  } 

}

parseNumber(String number) {
  parsedNumber = ...
  return parsedNumber;
}

答案 1 :(得分:0)

看起来很不错但你想要分离树的构建和评估:

public class DiffExp implements LetLangExp {
  LetLangExp left, right;

  public DiffExp(LetLangExp l, LetLangExp r) {
    left = l;
    right = r;
  }

  public double eval() {
    return left.eval() - right.eval();
  }
}

P.S。解析应大致如下:

LetLangExpr parseProgram(LinkedList<String> tokens) {
  return parseExpression(tokens);
}

LetLangExpr parseExpression(LinkedList<String> tokens) {
  if ("-".equals(tokenStream.peekFirst())) {
    return parseDiff(tokens);
  } else {
    return parseNumber(tokens);
  }
}

LetLangExpr parseDiff(LinkedList<String> tokens) {
  tokens.pollFirst();  // Consume "-"
  LetLangExpr left = parseExpression(tokens);
  LetLangExpr right = parseExpression(tokens);
  return new DiffExpr(left, right);
}

LetLangExpr parseNumber(LinkedList<String> tokens) {
  String numberStr = tokens.pollFirs();
  double number = Double.parseDouble(numberStr);
  return new NumberExpr(number);
}