Как arity.jar арифметическая библиотека вычисляет строку операции?

#java #eval

#java #eval

Вопрос:

Привет всем, недавно я наткнулся на библиотеку Arity -> источник можно найти здесь и обнаружил, что она оценивает строку как арифметическую операцию с использованием метода .eval(), посмотрев на источник, я нашел этот метод объекта Symbols:

 /**
       Evaluates a simple expression (such as "1 1") and returns its value.
       @throws SyntaxException in these cases:
       <ul>
       <li> the expression is not well-formed
       <li> the expression is a definition (such as "a=1 1")
       <li> the expression is an implicit function (such as "x 1")
       </ul>
     */
    public synchronized double eval(String expression) throws SyntaxException {
        return compiler.compileSimple(this, expression).eval();
    }
  

Этот метод вызывает .compileSimple объекта компиляции компилятора:

 Function compileSimple(Symbols symbols, String expression) throws SyntaxException {
    rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
    lexer.scan(expression, rpn);
    return simpleCodeGen.getFun();
}
  

Которая возвращает объект функции, а затем вызывает для него метод eval(). Глядя на метод Function.eval(), я увидел это:

 /**
       Evaluates an arity-0 function (a function with no arguments).
       @return the value of the function
    */
    public double eval() {
        throw new ArityException(0);
    }
  

Метод eval должен возвращать тип double, а реализация выдает исключение ArityException, которое имеет эту реализацию:

 public class ArityException extends RuntimeException {
    public ArityException(String mes) {
        super(mes);
    }

    public ArityException(int nArgs) {
        this("Didn't expect "   nArgs   " arguments");
    }
}
  

Но когда генерируется исключение ArityException, оно вызывает конструктор super() исключения RuntimeException, и это исключение, и не возвращается double, как должно быть, возможно, я перепутал некоторые отрывки, но я не понял, что последнее исключение ArityException равно 0 внутри реализации Function.eval() .

Итак, как это действительно работает?

Ответ №1:

Вы пропустили объявление simpleCodeGen :

 private final SimpleCodeGen simpleCodeGen = new SimpleCodeGen(exception);
  

Это означает, что compileSimple(...) на самом деле возвращает a CompiledFunction , который расширяет ContextFunction и тому подобное Function .

 CompiledFunction getFun() {
    return new CompiledFunction(0, code.toArray(), consts.getRe(), consts.getIm(), funcs.toArray());
}
  

Так eval(...) что на самом деле это ContextFunction вызываемая функция. У этого есть реальная реализация.

Выполнение анализа кода без IDE и просто просмотр кода могут быть сложными. Использование отладчика и пошаговое выполнение легко покажет вам поток программы.

Комментарии:

1. Спасибо за объяснение!