Библиотека позволяет вам обрабатывать и исполнять выражения. Синтаксис практически идентичен синтаксису 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