simple-expr
Simple expression language for mapbox-gl-js expressions
The primary aim of this language is to support MapboxGL expressions, although it should also be generally useful.
This is a tiny functional language that gets converted into MapboxGL expressions. The idea behind the language is that it can be converted in a lossless way between MapboxGL expressions and back again.
Basically it's just a nicer way to write MapboxGL expressions. Here's an example, the following JSON
[
"interpolate",
["linear"], ["get", "score"],
0, ["rgb", 255, 0, 0],
50, ["rgb", 0, 255, 0],
100, ["rgb", 0, 0, 255]
]
Would be written as
interpolate(
linear(), @score,
0, rgb(255, 0, 0),
50, rgb(0, 255, 0),
100, rgb(0, 0, 255)
)
See it in action: https://orangemug.github.io/simple-expr
Install
To install
npm install orangemug/simple-expr --save
Syntax
You are only allowed to define a single top level expression.
Valid
rgb(255, 0, 0)
Invalid!
rgb(255, 0, 0)
rgb(0, 0, 255)
Although sub expressions are allowed
rgb(get("rank"), 0, 0)
Types
There are 2 basic types
number
Any integer or decimal number not in quotes, for example
1
-1
+3
3.14
-1000
-9.8
string
Any characters surrounded in quotes, for example
"foo bar"
You can escape quotes with \
for example
"They said \"it couldn't be done\""
Functions
Functions are defined as
function_name(arg, arg, arg...)
Note that arguments can also be functions. This gets compiled into the MapboxGL expressions JSON format.
Lets see an example
rgb(get("rating"), 0, 0)
Will become
["rgb", ["get", "rating"], 0, 0]
Feature references
As well as using the get
function (see spec) there is also a shorthand to reference feature data. The following
rgb(@rating, 0, 0)
Is the same as
rgb(get("rating"), 0, 0)
Variables
NOTE: Not yet available
You can also define variables before the expressions. Variables are also allowed to define a single expression. A quick example
&r = interpolate(
linear(), @score,
1, 100
22, 255
)
rgb(&r, 0, 0)
Variables must start with a &
both in there definition and their usage.
Usage
You can parse, compile to JSON. It comes in 2 forms, the CLI (command line interface) and the JavaScript API
JavaScript API
Compile to expression JSON
var simpleExpr = require("simple-expr");
var out = simpleExpr.compiler('concat("hello", " ", "world")', {format: "json"})
assert.deepEqual(out, [
"concat", "hello", " ", "world"
])
Parse to AST
var simpleExpr = require("simple-expr");
var tokens = simpleExpr.tokenizer('concat("hello", " ", "world")')
var ast = simpleExpr.parser(tokens);
assert.deepEqual(ast, {
"type": "Program",
"body": [
{
"type": "CallExpression",
"name": "concat",
"params": [
{
"type": "StringLiteral",
"value": "hello"
},
{
"type": "StringLiteral",
"value": " "
},
{
"type": "StringLiteral",
"value": "world"
}
]
}
]
})
CLI
The available CLI commands are
Parse
simple-expr parse examples/concat.expr > /tmp/concat.ast
## >>/tmp/concat.ast
## {
## "type": "Program",
## "body": [
## {
## "type": "CallExpression",
## "name": "concat",
## "params": [
## {
## "type": "StringLiteral",
## "value": "Hello"
## },
## {
## "type": "StringLiteral",
## "value": " "
## },
## {
## "type": "FeatureRef",
## "value": "name"
## }
## ]
## }
## ]
## }
## <<
Compile
simple-expr compile examples/concat.expr > /tmp/concat.json
## >>/tmp/concat.json
## [
## "concat",
## "Hello",
## " ",
## [
## "get",
## "name"
## ]
## ]
## <<
Decompile
simple-expr decompile examples/concat.json > /tmp/concat.expr
## >>/tmp/concat.expr
## concat("Hello", " ", @name)
## <<
Execute
simple-expr execute --feature-props name=Maputnik examples/concat.expr > /tmp/concat.log
## >>/tmp/concat.log
## Hello Maputnik
## <<