Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/justinfagnani/jexpr
A simple expression parser and evaluator for JavaScript
https://github.com/justinfagnani/jexpr
Last synced: 6 days ago
JSON representation
A simple expression parser and evaluator for JavaScript
- Host: GitHub
- URL: https://github.com/justinfagnani/jexpr
- Owner: justinfagnani
- License: bsd-3-clause
- Created: 2021-01-30T20:08:51.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-03-25T15:23:17.000Z (8 months ago)
- Last Synced: 2024-04-26T00:42:32.227Z (7 months ago)
- Language: TypeScript
- Size: 601 KB
- Stars: 53
- Watchers: 4
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Authors: AUTHORS
Awesome Lists containing this project
README
# Jexpr
## Overview
Jexpr is an expression syntax, parser, and evaluator for JS-like expressions.
Jexpr is designed for libraries that evaluate user-written expressions, such as
HTML templating engines. Jexpr has a relatively rich syntax, supporting
identifiers, operators, property access, method and function calls, and
literals (including arrays and objects), function literals, assignments,
and pipes.Example:
```js
(person.title + ' ' + person.getFullName()) | uppercase;
```## Usage
### Installation
```bash
npm i jexpr
```### Usage
```ts
import {parse, EvalAstFactory} from 'jexpr';// An EvalAstFactory produces an AST that can be evaluated
const astFactory = new EvalAstFactory();// parse() returns the AST
const expr = parse('(a + b([1, 2, 3]) * c)', astFactory);// evaluate() with a scope object
const result = expr.evaluate({
a: 42,
b: (o: Array) => o.length,
c: 2,
});console.log(result); // 48
```## Features
### Fast, small parser
Jexpr is a hand-written, recursive descent, precedence-climbing parser. It's
simple, fast and small.### Pluggable AST factories
`parse()` takes an AST factory so that different strategies can be used to
produce ASTs. The default factory creates an AST as defined in `lib/ast.js`.
`lib/eval.js` exports an `EvalAstFactory` that produces evaluatable ASTs.### Null-Safety
Expressions are generally null-safe. If a subexpression yields `null` or
`undefined`, subsequent property access will return null, rather than throwing
an exception. Property access, method invocation and operators are null-safe.
Passing null to a function that doesn't handle null will not be null safe.## Syntax
### Property access
Properties on the model and in the scope are looked up via simple property
names, like `foo`. Property names are looked up first in the top-level
variables, next in the model, then recursively in parent scopes. Properties on
objects can be access with dot notation like `foo.bar`.The keyword `this` always refers to the model if there is one, otherwise `this`
is `null`. If you have model properties and top-level variables with the same
name, you can use `this` to refer to the model property.### Literals
Jexpr supports number, boolean, string, and map literals. Strings
can use either single or double quotes.- `null` and `undefined`
- Numbers: `1`, `1.0`
- Booleans: `true`, `false`
- Strings: `'abc'`, `"xyz"`
- Objects: `{ 'a': 1, 'b': 2 }`
- Arrays: `[1, 2, 3]`### Function and method calls
If a property is a function in the scope, a method on the model, or a method on
an object, it can be invoked with standard function syntax. Functions and
Methods can take arguments. Arguments can be literals or variables.Examples:
- Top-level function: `myFunction()`
- Top-level function with arguments: `myFunction(a, b, 42)`
- Model method: `aMethod()`
- Method on nested-property: `a.b.anotherMethod()`### Operators
Jexpr supports the following binary and unary operators:
- Assignment: `=`
- Arithmetic operators: `+`, `-`, `*`, `/`, `%`, unary `+` and `-`
- Comparison operators: `==`, `!=`, `===`, `!==`, `<=`, `<`, `>`, `>=`
- Boolean operators: `&&`, `||`, unary `!`
- Nullish coalescing: `??`
- Pipeline operators: `|` (legacy) and `|>` (modern)Expressions do not support bitwise operators such as `&`, `|`, `<<` and `>>`, or
increment/decrement operators (`++` and `--`)#### Assignment
The left-hand-side expression of the assignment operator (`=`) must be one of an
ID, getter or setter, otherwise an exception is thrown.### Maps
Maps are sets of key/value pairs. The key can either be a quoted string, or an
identifier:Examples:
- `{'a': 1, 'b': 2}`
- `{a: 1, b: 2}`### Array and Object indexing
Arrays and objects can be accessed via the index operator: []
Examples:
- `items[2]`
- `people['john']`### Function expressions
Functions can be written with the arrow function syntax.
Examples:
- `() => 3`
- `(a, b) => a + b`### Filters and transformers
A filter is a function that transforms a value into another, used via the pipe
syntax: `value | filter` Any function that takes exactly one argument can be
used as a filter.Example:
If `person.name` is `"John"`, and a top-level function named `uppercase` has
been registered, then `person.name | uppercase` will have the value `"JOHN"`.The pipe syntax is used rather than a regular function call so that we can
support two-way bindings through transformers. A transformer is a filter that
has an inverse function. Two-way transformers are not supported yet.## Acknowedgements
Jexpr is forked from `polymer-expressions` which is no longer officially
maintained by the Polymer team. The JavaScript version of that library was
ported from the
[Dart library](https://github.com/dart-archive/polymer-expressions) of the same
name, originally used in Polymer.dart.