Библиотека позволяет вам обрабатывать и исполнять выражения. Синтаксис практически идентичен синтаксису Java.
Выполнение арифметического выражения с известными числами
class Example {
@Test
public void testArithmeticEvaluation() {
Jexpr jexpr = DefaultJexpr.create();
assertEquals(30, jexpr.parse("5 + 5 * 5").getValue());
}
}Выполнение арифметического выражения с неизвестными числами
class Example {
@Test
public void testArithmeticEvaluation() {
Jexpr jexpr = DefaultJexpr.create();
// Переменные запрашиваются через UndefinedResolver,
// реализацией которого может быть всё что угодно.
//
// В данном примере, для простоты демонстрации,
// мы получаем значения переменных из Map.
Map<String, Operand> variables = Map.of(
"x", Operands.constantInt(1),
"y", Operands.constantInt(2),
"z", Operands.constantInt(3)
);
Operand operand = jexpr.parse("x + y * z");
Operand solvedOperand = operand.solve(variables::get);
assertEquals(7, solvedOperand.getValue());
}
}С помощью модуля jexpr-compiler вы можете компилировать неопределённые выражения (содержащие переменные)
напрямую в байткод. Реализованы все операторы из jexpr-core.
class Example {
public void compile(MethodVisitor mv) {
Jexpr jexpr = DefaultJexpr.create();
JexprCompiler jexprCompiler = DefaultJexprCompiler.create();
// парсим выражение
Operand operand = jexpr.parse("variable + 1");
// Указываем, что у нас находится в локальных переменных
// они будут использованы компилятором
LocalMap localMap = SimpleLocalMap.create()
// в параметре 1 у нас целое число с именем variable.
// при компиляции оно увидит неизвестное "variable" и
// запросит его на стек из локальных параметров
.add("variable", 1, Type.INT_TYPE);
jexprCompiler.compile(mv, localMap, operand);
// Результат:
//
// ILOAD_1
// ICONST_1
// IADD
}
}Также есть упрощенный функционал, который может создать нужную реализацию функционального интерфейса.
import java.util.function.IntBinaryOperator;
class Example {
public IntBinaryOperator sum() {
Jexpr jexpr = DefaultJexpr.create();
JexprCompiler jexprCompiler = DefaultJexprCompiler.create();
Operand operand = jexpr.parse("a + b");
return jexprCompiler.implementInterface(IntBinaryOperator.class)
.name(0, "a")
.name(1, "b")
.compile(operand);
}
}Объекты и строки можно сравнивать используя операторы == и !=, эти операторы будут заменены
на equals (даже при генерации байткода через jexpr-compiler).
Объекты можно вставить в Operand используя метод solve, но при генерации байткода
произвольные объекты недопустимы, поскольку их нельзя записать в формате байткода.
В полной мере реализована
поддержка Escape-последовательностей,
например: \0, \u89ab, \n, \\, \"
На данный момент реализованы все операторы, которые существуют в Java, за исключением тройного (тернарного) оператора.
| Категория | Операторы |
|---|---|
| Побитовые | ~ | & << >> >>> ^ |
| Логические | ! || && == != > < >= <= |
| Арифметические | * / + - % |
Синтаксис чисел полностью взят из Java
- Префиксы
0x,0bи0[0-7]у целых чисел - Суффиксы
Ll,Ff,Dd - Начало числа с
. - Нижнее подчёркивание (
_) в числе - Экспоненциальная запись (
1e-2345)
Отсутствует обработка чисел с плавающей точкой в 16ричной системе счисления.
Используется на стадии обработки текста. Список ключевых слов и их значение зафиксированы для парсера и не могут быть изменены.
Доступные ключевые слова по-умолчанию:
| Название | Значение |
|---|---|
true |
OperandBoolean.TRUE |
false |
OperandBoolean.FALSE |
null |
OperandObject.NULL |
TODO
Код под лицензией Apache License 2.0