{"id":25804596,"url":"https://github.com/alessandro-salerno/forflex","last_synced_at":"2026-06-08T01:32:03.408Z","repository":{"id":279709552,"uuid":"939033390","full_name":"Alessandro-Salerno/Forflex","owner":"Alessandro-Salerno","description":"Flexible expression evaluation library","archived":false,"fork":false,"pushed_at":"2025-10-20T19:24:47.000Z","size":118,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-20T21:25:56.729Z","etag":null,"topics":["algebra","expression-parser","expressions","flexible","flexible-library","flexible-parsers","java","java-library","lexer","library","math","math-parser","parser"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Alessandro-Salerno.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-25T22:11:07.000Z","updated_at":"2025-10-20T19:24:51.000Z","dependencies_parsed_at":"2025-02-27T01:33:03.521Z","dependency_job_id":"c20bb2f4-035f-452d-825d-4b3575cd6311","html_url":"https://github.com/Alessandro-Salerno/Forflex","commit_stats":null,"previous_names":["alessandro-salerno/forflex"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Alessandro-Salerno/Forflex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2FForflex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2FForflex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2FForflex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2FForflex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alessandro-Salerno","download_url":"https://codeload.github.com/Alessandro-Salerno/Forflex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2FForflex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34044919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algebra","expression-parser","expressions","flexible","flexible-library","flexible-parsers","java","java-library","lexer","library","math","math-parser","parser"],"created_at":"2025-02-27T18:52:55.297Z","updated_at":"2026-06-08T01:32:03.403Z","avatar_url":"https://github.com/Alessandro-Salerno.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ch1 align=\"center\"\u003eForflex\u003c/h1\u003e\n    \u003cp align=\"center\"\u003e Simple, flexible, and extensible expression parseing and evaluation library for Java \u003c/p\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[contributors-shield]: https://img.shields.io/github/contributors/Alessandro-Salerno/Forflex.svg?style=flat-square\n[contributors-url]: https://github.com/Alessandro-Salerno/Forflex/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/Alessandro-Salerno/Forflex.svg?style=flat-square\n[forks-url]: https://github.com/Alessandro-Salerno/Forflex/network/members\n[stars-shield]: https://img.shields.io/github/stars/Alessandro-Salerno/Forflex.svg?style=flat-square\n[stars-url]: https://github.com/Alessandro-Salerno/Forflex/stargazers\n[issues-shield]: https://img.shields.io/github/issues/Alessandro-Salerno/Forflex.svg?style=flat-square\n[issues-url]: https://github.com/Alessandro-Salerno/Forflex/issues\n[license-shield]: https://img.shields.io/github/license/Alessandro-Salerno/Forflex.svg?style=flat-square\n[license-url]: https://github.com/Alessandro-Salerno/Forflex/blob/master/LICENSE.txt\n\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n![](https://tokei.rs/b1/github/Alessandro-Salerno/Forflex)\n\n\u003c/div\u003e\n\n## Features\n- Java function invocation inside expressions\n- Expression parameters\n- Real and string algebras included\n- Custom algebric structures other than real numbers\n- Parse tree caching\n- Error handling\n- Can be used in both FOSS and proprietary software\n\n## Syntax and grammar\nThe grammar is defined in pseudo-BNF as follows:\n```\nGrammar:\n    \u003csymbol\u003e     := anything in UTF-8\n    \u003cdigit\u003e      := 0|1|2|3|4|5|6|7|8|9\n    \u003cinteger\u003e    := \u003cdigit\u003e{\u003cdigit\u003e}*\n    \u003cnum\u003e        := \u003cinteger\u003e[.\u003cinteger\u003e]\n    \u003clowercase\u003e  := a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z\n    \u003cuppercase\u003e  := A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z\n    \u003cletter\u003e     := \u003clowercase\u003e|\u003cuppercase\u003e\n    \u003cstring\u003e     := \"{\u003csymbol\u003e}*\"\n    \u003cidentifier\u003e := \u003cletter\u003e|_{\u003cletter\u003e|\u003cdigit\u003e|_}*\n    \u003cexpr\u003e       := \u003cterm\u003e[{+|-}\u003cterm\u003e]\n    \u003cparams\u003e     := [\u003cexpr\u003e{, \u003cexpr\u003e}*]\n    \u003ccall\u003e       := \u003cidentifier\u003e(\u003cparams\u003e)\n    \u003cterm\u003e       := \u003cfactor\u003e[{*|/}\u003cfactor\u003e]\n    \u003cfactor\u003e     := -\u003cfactor\u003e|(\u003cexpr\u003e)|\u003cnumber\u003e|\u003cidentifier\u003e|\u003ccall\u003e|\u003cstring\u003e\n```\n\nFor example, this is a valid statement:\n```\nround((a + b + c - d) / (5.47 * sin(1)) + priceof(\"AAPL\", \"2025-02-26\"))\n```\nHowever, the round functions and the other symbols must be defied by the Java program, otherwise an exception is thrown:\n```\n1:1 ERROR: Undeclared identifier \"round\"\n 1 | round((a + b + c - d) / (5.47 * sin(1)) + priceof(\"AAPL\", \"2025-02-26\"))\n   | ~~~~~\n```\n\n## Structure\nForflex has six main concepts:\n- Algebric structures\n- Evaluables\n- Expressions\n- Functions\n- Parameters\n- Parser\n\n### Algebric structures\nAlgebric structures in Forflex define what operations can be applied to a number and how these operations behave. Algebric structures are classes that implement `ForflexAlgebra` and define methods for addition, subtraction, multiplication, and division. If a given algebric structure does not support one or more of these operations, it can throw a `ForflexUnsupportedOperationError`. The default algebric structure is `ForflexRealNumber`.\n\n### Evaluables\nEvaluables in Forflex are essentially nodes in the parse tree. Evaluables implement the `ForflexEvaluable` interface and its method `evaluate` which returns an instance of a `ForflexAlgebra` when called.\nForflex ships with four main evaluables:\n- Identity (`ForflexIdentityNode` - returns the same instance of `ForflexAlgebra` that was passed)\n- Binary (`ForflexBinaryNode` - holds two other evaluables on the left and right in order to make the binary tree)\n- Function call (`ForflexFunctionCallNode` - used to represent a function call in the tree)\n- Parameter (`ForflexParameterNode` - used to store references to parameters)\n\n### Expressions\nExpressions in Forflex are a special type of evaluable which stands outside the tree and is used to cache the tree itself in order to reuse it. This removes the need to reparse the expression every time it has to be evaluated with a given set of parameters.\n\n### Functions\nFunctions in Forflex are implementations of the `ForflexFunction` interface which, once added to a Parser, can be invoked from within an expression.\n\n### Parameters\nParameters in Forflex are named values that reside in the host Java program but can be access in read-only mode within expressions.\n\n### Parser\nThe Parser (`ForflexParser`) is the component responsible for constructing the tree. It first tokenizes the expression using the Lexer and then recursively scrolls the token list to build the tree.\n\n## Example\n\n```java\nimport alessandrosalerno.forflex.*;\nimport alessandrosalerno.forflex.errors.preprocessor.ForflexPreprocessorError;\nimport alessandrosalerno.forflex.algebra.ForflexAlgebra;\nimport alessandrosalerno.forflex.algebra.ForflexRealNumber;\nimport alessandrosalerno.forflex.errors.runtime.ForflexArgumentCountError;\nimport alessandrosalerno.forflex.errors.runtime.ForflexArgumentTypeError;\nimport alessandrosalerno.forflex.errors.runtime.ForflexUnassignedParametersError;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        try {\n            String formula = \"round((a + b + c - d) / (5.47 * sin(1)) + priceof(\\\"AAPL\\\", \\\"2025-02-26\\\"))\";\n            ForflexParameterSpec parameterSpec = new ForflexParameterSpec()\n                                                        .addParam(\"a\")\n                                                        .addParam(\"b\")\n                                                        .addParam(\"c\")\n                                                        .addParam(\"d\");\n\n            ForflexParser parser = new ForflexParser()\n                                            .addFunctions(ForflexUtils.DEFAULT_FUNCTIONS)\n                                            .addFunction(\"priceof\", new ForflexFunction\u003cForflexRealNumber\u003e() {\n                @Override\n                public ForflexRealNumber run(ForflexAlgebra\u003c?\u003e[] args) {\n                    String symbol = ForflexUtils.requireArgumentPrimitiveType(args, 0, String.class);\n                    String date = ForflexUtils.requireArgumentPrimitiveType(args, 1, String.class);\n                    // Do some magic stock market stuff\n                    return new ForflexRealNumber(200.5);\n                }\n            });\n\n            ForflexExpression expr = parser.parse(formula, parameterSpec);\n            ForflexParameterAssignment parameterAssignment = new ForflexParameterAssignment(parameterSpec)\n                                                                    .assign(\"a\", new ForflexRealNumber(1))\n                                                                    .assign(\"b\", new ForflexRealNumber(2))\n                                                                    .assign(\"c\", new ForflexRealNumber(3))\n                                                                    .assign(\"d\", new ForflexRealNumber(4));\n            ForflexRealNumber result = (ForflexRealNumber) expr.evaluate(parameterAssignment);\n            System.out.println(result.getPrimitive());\n        } catch (ForflexPreprocessorError e) {\n            e.printErrorMessage();\n        } catch (ForflexArgumentCountError\n                 | ForflexArgumentTypeError\n                 | ForflexUnassignedParametersError e) {\n            e.printStackTrace();\n        }\n    }\n}\n```\n\n## Installing Forflex with Maven\nYou can install Forflex using the official [GitHub Package](https://github.com/Alessandro-Salerno/Forflex/packages/2419537).\n\nAlternatively, you can download and install it manually. After downloading the JAR and placing it in some project directory (e.g., resources), use the following dependency structure in your pom.xml file:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ealessandrosalerno.forflex\u003c/groupId\u003e\n    \u003cartifactId\u003eforflex\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.2\u003c/version\u003e\n    \u003cscope\u003esystem\u003c/scope\u003e\n    \u003csystemPath\u003e${project.basedir}/src/main/resources/forflex-1.0.2.jar\u003c/systemPath\u003e\n\u003c/dependency\u003e\n```\n\n## License\nForflex is distributed under the Apache License 2.0.\n\n## Credits\n- https://github.com/javalc6/Simple-Expression-Parser\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessandro-salerno%2Fforflex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falessandro-salerno%2Fforflex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessandro-salerno%2Fforflex/lists"}