subscript 5.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -44
- package/evaluate.js +37 -37
- package/justin.js +48 -49
- package/justin.min.js +1 -1
- package/package.json +1 -1
- package/parse.js +1 -1
- package/subscript.min.js +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# <img alt="subscript" src="/subscript2.svg" height=42/> <!--sub͘<em>script</em>--> <!--<sub>SUB͘<em>SCRIPT</em></sub>-->
|
|
2
2
|
|
|
3
3
|
_Subscript_ is micro-language with common syntax subset of C++, JS, Java, Python, Go, Rust, Swift, Objective C, Kotlin etc.<br/>
|
|
4
4
|
|
|
@@ -27,28 +27,9 @@ _Subscript_ is designed to be useful for:
|
|
|
27
27
|
* custom DSL
|
|
28
28
|
|
|
29
29
|
[_Jsep_](https://github.com/EricSmekens/jsep) is generally fine for the listed tasks, unless you need dependencies as small as possible.
|
|
30
|
-
_Subscript_ has [2.5kb](https://npmfs.com/package/subscript/
|
|
30
|
+
_Subscript_ has [2.5kb](https://npmfs.com/package/subscript/5.0.0/subscript.min.js) footprint vs [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_, with better performance.
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
## Operators
|
|
34
|
-
|
|
35
|
-
Default operators include common operators for the listed languages in the following precedence:
|
|
36
|
-
|
|
37
|
-
* `++ --` unary postfix
|
|
38
|
-
* `! + - ++ --` unary prefix
|
|
39
|
-
* `* / %`
|
|
40
|
-
* `+ -`
|
|
41
|
-
* `<< >> >>>`
|
|
42
|
-
* `< <= > >=`
|
|
43
|
-
* `== !=`
|
|
44
|
-
* `&`
|
|
45
|
-
* `^`
|
|
46
|
-
* `|`
|
|
47
|
-
* `&&`
|
|
48
|
-
* `||`
|
|
49
|
-
|
|
50
|
-
All other operators can be extended, see [extension](#extension).
|
|
51
|
-
|
|
52
33
|
## Evaluation
|
|
53
34
|
|
|
54
35
|
_Subscript_ parser generates lispy calltree (compatible with [frisk](https://npmjs.com/frisk)), which is compared to esprima AST has:
|
|
@@ -66,34 +47,32 @@ import {evaluate} from 'subscript.js'
|
|
|
66
47
|
evaluate(['+', ['*', 'min', 60], '"sec"'], { min: 5 }) // min*60 + "sec" == "300sec"
|
|
67
48
|
```
|
|
68
49
|
|
|
69
|
-
##
|
|
70
|
-
|
|
71
|
-
Tokens are extensible via `parse.token` list, can be added support of _regex_, _array_, _object_, _interpolated string_ and others.
|
|
72
|
-
Default tokens include:
|
|
73
|
-
|
|
74
|
-
* `"abc"` strings
|
|
75
|
-
* `1.2e+3` floats
|
|
76
|
-
* `()` expression groups or fn calls
|
|
77
|
-
* `.`, `[]` property access
|
|
50
|
+
## Extending
|
|
78
51
|
|
|
79
|
-
|
|
52
|
+
Default operators include common operators for the listed languages in the following precedence:
|
|
80
53
|
|
|
81
|
-
|
|
54
|
+
* `++ --` unary postfix
|
|
55
|
+
* `! + - ++ --` unary prefix
|
|
56
|
+
* `* / %`
|
|
57
|
+
* `+ -`
|
|
58
|
+
* `<< >> >>>`
|
|
59
|
+
* `< <= > >=`
|
|
60
|
+
* `== !=`
|
|
61
|
+
* `&`
|
|
62
|
+
* `^`
|
|
63
|
+
* `|`
|
|
64
|
+
* `&&`
|
|
65
|
+
* `||`
|
|
82
66
|
|
|
83
|
-
|
|
67
|
+
Operators can be extended via `parse.operator(str, prec, type)` and `evaluate.operator(str, fn)` functions for any unary/binary/postfix operators, calls, props, groups, arrays, objects etc.
|
|
84
68
|
|
|
85
|
-
<!--
|
|
86
69
|
```js
|
|
87
70
|
import { parse, evaluate } from 'subscript.js'
|
|
88
71
|
|
|
89
|
-
//
|
|
90
|
-
// TODO
|
|
91
|
-
// parse.operator['=>'] = 10
|
|
72
|
+
parse.operator('=>', 10) // precedence=10, type=default (0 - binary, 1 - postfix, -1 - prefix)
|
|
92
73
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// evaluate.operator['=>'] = ( args, body ) => evaluate(body, args)
|
|
96
|
-
// evaluate.operator['|'] = ( a, ...b ) => a.pipe(...b)
|
|
74
|
+
evaluate.operator('=>', ( args, body ) => evaluate(body, args))
|
|
75
|
+
evaluate.operator('|', ( a, ...b ) => a.pipe(...b))
|
|
97
76
|
|
|
98
77
|
let tree = parse(`
|
|
99
78
|
interval(350)
|
|
@@ -103,7 +82,28 @@ let tree = parse(`
|
|
|
103
82
|
`)
|
|
104
83
|
evaluate(tree, { Math, map, take, interval, gaussian })
|
|
105
84
|
```
|
|
106
|
-
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
|
|
89
|
+
Default tokens include:
|
|
90
|
+
|
|
91
|
+
* `"abc"` strings
|
|
92
|
+
* `1.2e+3` floats
|
|
93
|
+
* identifiers
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
import parse, {char} from 'subscript/parse.js'
|
|
97
|
+
import evaluate from 'subscript/evaluate.js'
|
|
98
|
+
|
|
99
|
+
conts ctx = {x:1}
|
|
100
|
+
parse.token.unshift(c => char(4) === 'this' ? ctx : null)
|
|
101
|
+
evaluate(parse(`this.x`)) // 1
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
Comments can be added via extending `parse.space`. See [justin.js](./justin.js) for more examples.
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
## Justin
|
|
@@ -111,6 +111,7 @@ evaluate(tree, { Math, map, take, interval, gaussian })
|
|
|
111
111
|
_Justin_ extension (original [thread](https://github.com/endojs/Jessie/issues/66)) is minimal JS subset − JSON with JS expressions.<br/>
|
|
112
112
|
It adds support of:
|
|
113
113
|
|
|
114
|
+
+ `===`, `!==` operators
|
|
114
115
|
+ `**` binary operator
|
|
115
116
|
+ `~` unary operator
|
|
116
117
|
+ `'` strings
|
|
@@ -122,7 +123,6 @@ It adds support of:
|
|
|
122
123
|
+ unary word operators
|
|
123
124
|
+ `//`, `/* */` comments
|
|
124
125
|
+ `true`, `false`, `null`, `undefined` literals
|
|
125
|
-
<!-- + `===`, `!==` operators -->
|
|
126
126
|
<!-- + `?` chaining operator -->
|
|
127
127
|
<!-- + `...x` unary operator -->
|
|
128
128
|
<!-- + strings interpolation -->
|
|
@@ -279,7 +279,7 @@ Subscript shows relatively good performance within other evaluators:
|
|
|
279
279
|
// 1 + (a * b / c % d) - 2.0 + -3e-3 * +4.4e4 / f.g[0] - i.j(+k == 1)(0)
|
|
280
280
|
// parse 30k times
|
|
281
281
|
|
|
282
|
-
subscript: ~
|
|
282
|
+
subscript: ~220 ms
|
|
283
283
|
jsep: ~280 ms
|
|
284
284
|
expr-eval: ~480 ms
|
|
285
285
|
jexl: ~1200 ms
|
package/evaluate.js
CHANGED
|
@@ -4,10 +4,9 @@ export const isCmd = a => Array.isArray(a) && (typeof a[0] === 'string' || isCmd
|
|
|
4
4
|
evaluate = (s, ctx={}, c, op) => {
|
|
5
5
|
if (isCmd(s)) {
|
|
6
6
|
c = s[0]
|
|
7
|
-
if (typeof c === 'string') op =
|
|
7
|
+
if (typeof c === 'string') op = lookup[c]
|
|
8
8
|
c = op || evaluate(c, ctx) // [[a,b], c]
|
|
9
9
|
if (typeof c !== 'function') return c
|
|
10
|
-
|
|
11
10
|
return c.call(...s.map(a => evaluate(a,ctx)))
|
|
12
11
|
}
|
|
13
12
|
if (s && typeof s === 'string')
|
|
@@ -17,43 +16,44 @@ evaluate = (s, ctx={}, c, op) => {
|
|
|
17
16
|
|
|
18
17
|
return s
|
|
19
18
|
},
|
|
20
|
-
|
|
21
|
-
reducer=fn=>(...a)=>a.reduce(fn),
|
|
19
|
+
lookup = {},
|
|
22
20
|
|
|
23
21
|
// op evaluators
|
|
24
22
|
// multiple args allows shortcuts, lisp compatible, easy manual eval, functions anyways take multiple arguments
|
|
25
|
-
operator = evaluate.operator =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
'
|
|
29
|
-
|
|
30
|
-
'
|
|
31
|
-
|
|
32
|
-
'
|
|
33
|
-
|
|
34
|
-
'
|
|
35
|
-
|
|
36
|
-
'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
'
|
|
40
|
-
|
|
41
|
-
'
|
|
42
|
-
|
|
43
|
-
'
|
|
44
|
-
|
|
45
|
-
'
|
|
46
|
-
'
|
|
47
|
-
|
|
48
|
-
'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
'
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
',
|
|
57
|
-
|
|
23
|
+
operator = evaluate.operator = (op, fn) => lookup[op] = fn.length == 2 ? (...a)=>a.reduce(fn) : fn
|
|
24
|
+
|
|
25
|
+
for (let fn,ops = [
|
|
26
|
+
'!', a=>!a,
|
|
27
|
+
'++', a=>++a,
|
|
28
|
+
'--', a=>--a,
|
|
29
|
+
|
|
30
|
+
'.', (a,b)=>a?a[b]:a,
|
|
31
|
+
|
|
32
|
+
'%', (a,b)=>a%b,
|
|
33
|
+
'/', (a,b)=>a/b,
|
|
34
|
+
'*', (a,b)=>a*b,
|
|
35
|
+
|
|
36
|
+
'+', (a,b)=>a+b,
|
|
37
|
+
'-', (...a)=>a.length < 2 ? -a : a.reduce((a,b)=>a-b),
|
|
38
|
+
|
|
39
|
+
'>>>', (a,b)=>a>>>b,
|
|
40
|
+
'>>', (a,b)=>a>>b,
|
|
41
|
+
'<<', (a,b)=>a<<b,
|
|
42
|
+
|
|
43
|
+
'>=', (a,b)=>a>=b,
|
|
44
|
+
'>', (a,b)=>a>b,
|
|
45
|
+
'<=', (a,b)=>a<=b,
|
|
46
|
+
'<', (a,b)=>a<b,
|
|
47
|
+
|
|
48
|
+
'!=', (a,b)=>a!=b,
|
|
49
|
+
'==', (a,b)=>a==b,
|
|
50
|
+
|
|
51
|
+
'&', (a,b)=>a&b,
|
|
52
|
+
'^', (a,b)=>a^b,
|
|
53
|
+
'|', (a,b)=>a|b,
|
|
54
|
+
'&&', (...a)=>a.every(Boolean),
|
|
55
|
+
'||', (...a)=>a.some(Boolean),
|
|
56
|
+
',', (a,b)=>(a,b)
|
|
57
|
+
]; fn=ops.pop();) operator(ops.pop(),fn)
|
|
58
58
|
|
|
59
59
|
export default evaluate
|
package/justin.js
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
// justin lang https://github.com/endojs/Jessie/issues/66
|
|
2
2
|
import {evaluate} from './evaluate.js'
|
|
3
|
-
import {parse, code, char, skip, expr,
|
|
3
|
+
import {parse, code, char, skip, expr, err} from './parse.js'
|
|
4
4
|
|
|
5
|
-
//
|
|
6
|
-
operator(';', 1)
|
|
7
|
-
|
|
8
|
-
// ===, !==
|
|
9
|
-
operator('===', 9)
|
|
10
|
-
operator('!==', 9)
|
|
11
|
-
|
|
12
|
-
// undefined
|
|
5
|
+
// literals
|
|
13
6
|
const v = v => ({valueOf:()=>v})
|
|
14
7
|
parse.token.splice(2,0, c =>
|
|
15
8
|
c === 116 && char(4) === 'true' && skip(4) ? v(true) :
|
|
@@ -31,28 +24,6 @@ parse.token[1] = (q, qc, c, str) => {
|
|
|
31
24
|
}
|
|
32
25
|
const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
|
|
33
26
|
|
|
34
|
-
// **
|
|
35
|
-
evaluate.operator['**'] = (...args)=>args.reduceRight((a,b)=>Math.pow(b,a))
|
|
36
|
-
operator('**', 14)
|
|
37
|
-
|
|
38
|
-
// ~
|
|
39
|
-
operator('~', 13, -1)
|
|
40
|
-
evaluate.operator['~'] = a=>~a
|
|
41
|
-
|
|
42
|
-
// TODO ...
|
|
43
|
-
|
|
44
|
-
// ?:
|
|
45
|
-
evaluate.operator['?:']=(a,b,c)=>a?b:c
|
|
46
|
-
operator('?', 3, (node) => {
|
|
47
|
-
if (!node) err('Expected expression')
|
|
48
|
-
let a, b
|
|
49
|
-
skip(), parse.space(), a = expr()
|
|
50
|
-
if (code() !== 58) err('Expected :')
|
|
51
|
-
skip(), parse.space(), b = expr()
|
|
52
|
-
return ['?:', node, a, b]
|
|
53
|
-
})
|
|
54
|
-
// operator(':')
|
|
55
|
-
|
|
56
27
|
// /**/, //
|
|
57
28
|
parse.space = cc => {
|
|
58
29
|
while (cc = code(), cc <= 32) {
|
|
@@ -66,28 +37,10 @@ parse.space = cc => {
|
|
|
66
37
|
return cc
|
|
67
38
|
}
|
|
68
39
|
|
|
69
|
-
// in
|
|
70
|
-
evaluate.operator['in'] = (a,b)=>a in b
|
|
71
|
-
operator('in', 10, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(10)])
|
|
72
|
-
|
|
73
|
-
// []
|
|
74
|
-
evaluate.operator['['] = (...args) => Array(...args)
|
|
75
|
-
// as operator it's faster to lookup (no need to call extra rule check), smaller and no conflict with word names
|
|
76
|
-
operator('[', 20, (node,arg) => !node && (
|
|
77
|
-
skip(), arg=expr(0,93), skip(),
|
|
78
|
-
!arg ? ['['] : arg[0] === ',' ? (arg[0]='[',arg) : ['[',arg]
|
|
79
|
-
))
|
|
80
|
-
|
|
81
40
|
// {}
|
|
82
41
|
parse.token.unshift((cc, node) => (
|
|
83
42
|
cc === 123 && (skip(), node = map(['{', expr(0,125)]), skip(), node)
|
|
84
43
|
))
|
|
85
|
-
|
|
86
|
-
operator('}')
|
|
87
|
-
operator(':', 0)
|
|
88
|
-
evaluate.operator['{'] = (...args)=>Object.fromEntries(args)
|
|
89
|
-
evaluate.operator[':'] = (a,b)=>[a,b]
|
|
90
|
-
|
|
91
44
|
const map = (n, args) => {
|
|
92
45
|
if (!n[1]) args = []
|
|
93
46
|
else if (n[1][0]==':') args = [n[1]]
|
|
@@ -95,6 +48,52 @@ const map = (n, args) => {
|
|
|
95
48
|
return ['{', ...args]
|
|
96
49
|
}
|
|
97
50
|
|
|
51
|
+
// parse operators
|
|
52
|
+
for (let i = 0, ops = [
|
|
53
|
+
';', 1,,
|
|
54
|
+
'===', 9,,
|
|
55
|
+
'!==', 9,,
|
|
56
|
+
'**', 14,,
|
|
57
|
+
'~', 13, -1,
|
|
58
|
+
'?', 3, (node) => {
|
|
59
|
+
if (!node) err('Expected expression')
|
|
60
|
+
let a, b
|
|
61
|
+
skip(), parse.space(), a = expr()
|
|
62
|
+
if (code() !== 58) err('Expected :')
|
|
63
|
+
skip(), parse.space(), b = expr()
|
|
64
|
+
return ['?:', node, a, b]
|
|
65
|
+
},
|
|
66
|
+
'}',,,
|
|
67
|
+
':', 0,,
|
|
68
|
+
'in', 10, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(10)],
|
|
69
|
+
'[', 20, (node,arg) => !node && (
|
|
70
|
+
skip(), arg=expr(0,93), skip(),
|
|
71
|
+
!arg ? ['['] : arg[0] === ',' ? (arg[0]='[',arg) : ['[',arg]
|
|
72
|
+
)
|
|
73
|
+
]; i < ops.length;) parse.operator(ops[i++],ops[i++],ops[i++])
|
|
74
|
+
|
|
75
|
+
// evaluate operators
|
|
76
|
+
for (let i = 0, ops = [
|
|
77
|
+
// **
|
|
78
|
+
'**', (...args)=>args.reduceRight((a,b)=>Math.pow(b,a)),
|
|
79
|
+
|
|
80
|
+
// ~
|
|
81
|
+
'~', a=>~a,
|
|
82
|
+
|
|
83
|
+
// ?:
|
|
84
|
+
'?:', (a,b,c)=>a?b:c,
|
|
85
|
+
// parse.operator(':')
|
|
86
|
+
// in
|
|
87
|
+
'in', (a,b)=>a in b,
|
|
88
|
+
|
|
89
|
+
// []
|
|
90
|
+
'[', (...args) => Array(...args),
|
|
91
|
+
// as operator it's faster to lookup (no need to call extra rule check), smaller and no conflict with word names
|
|
92
|
+
'{', (...args)=>Object.fromEntries(args),
|
|
93
|
+
':', (a,b)=>[a,b]
|
|
94
|
+
]; i < ops.length;) evaluate.operator(ops[i++],ops[i++])
|
|
95
|
+
|
|
96
|
+
// TODO ...
|
|
98
97
|
// TODO: strings interpolation
|
|
99
98
|
|
|
100
99
|
export default parse
|
package/justin.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e
|
|
1
|
+
var e=r=>Array.isArray(r)&&("string"==typeof r[0]||e(r[0])),r=(a,n={},o,l)=>e(a)?("string"==typeof(o=a[0])&&(l=t[o]),"function"!=typeof(o=l||r(o,n))?o:o.call(...a.map((e=>r(e,n))))):a&&"string"==typeof a?'"'===a[0]?a.slice(1,-1):"@"===a[0]?a.slice(1):a in n?n[a]:a:a,t={},a=r.operator=(e,r)=>t[e]=2==r.length?(...e)=>e.reduce(r):r;for(let e,r=["!",e=>!e,"++",e=>++e,"--",e=>--e,".",(e,r)=>e&&e[r],"%",(e,r)=>e%r,"/",(e,r)=>e/r,"*",(e,r)=>e*r,"+",(e,r)=>e+r,"-",(...e)=>e.length<2?-e:e.reduce(((e,r)=>e-r)),">>>",(e,r)=>e>>>r,">>",(e,r)=>e>>r,"<<",(e,r)=>e<<r,">=",(e,r)=>e>=r,">",(e,r)=>e>r,"<=",(e,r)=>e<=r,"<",(e,r)=>e<r,"!=",(e,r)=>e!=r,"==",(e,r)=>e==r,"&",(e,r)=>e&r,"^",(e,r)=>e^r,"|",(e,r)=>e|r,"&&",(...e)=>e.every(Boolean),"||",(...e)=>e.some(Boolean),",",(e,r)=>r];e=r.pop();)a(r.pop(),e);var n,o,l=15,s=(e,r)=>(o=e,n=0,r=c(),n<o.length?f():r.valueOf()),f=(e="Bad syntax")=>{throw Error(e+" `"+o[n]+"` at "+n)},p=(e=1,r=n)=>{if("number"==typeof e)n+=e;else for(;e(u());)n++;return o.slice(r,n)},u=(e=0)=>o.charCodeAt(n+e),i=(e=1)=>o.substr(n,e),c=(e=0,r,t,a,n=0,o,l)=>{for(;(t=s.space())&&(l=d[t]?.(a,e)||!a&&h(t));)a=l;return r&&t!==r&&f("Unclosed paren"),a},v=(s.space=e=>{for(;(e=u())<=32;)n++;return e},s.token=[e=>(e=p((e=>e>47&&e<58||46==e)))&&((69==u()||101==u())&&(e+=p(2)+p((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?f("Bad number"):e),(e,r)=>34==e&&p()+p((r=>r-e))+p(),e=>p((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))]),h=(e,r=0,t)=>{for(;r<v.length;)if(t=v[r++](e))return t},d=[],g=s.operator=(e,r=0,t=0,a,o=e.charCodeAt(0),l=e.length,v=d[o],h=e.toUpperCase()!==e,g)=>(g=l<2?h?e=>u(1)<=32:e=>1:h?r=>i(l)==e&&u(l)<=32:r=>i(l)==e,a=t?t>0?e=>e&&[p(l),e]:t<0?e=>!e&&[p(l),(c(r-1)||f()).valueOf()]:t:t=>{t=[e,t||f()];do{n+=l,t.push((c(r)||f()).valueOf())}while(s.space()==o&&g());return t},d[o]=(e,t)=>t<r&&g()&&a(e)||v&&v(e,t));for(let e=0,r=[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",l,-1,"++",l,-1,"++",l,1,"-",12,,"-",l,-1,"--",l,-1,"--",l,1,"!",l,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[p(),e,"string"==typeof(r=c(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(n++,e=[".",e,c(0,93).valueOf()],n++,e),"]",,,"(",18,(e,r)=>(n++,r=c(0,41),n++,Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,r.valueOf()]:[e]),"(",19,(e,r)=>!e&&(++n,r=c(0,41)||f(),++n,r),")",,,];e<r.length;)g(r[e++],r[e++],r[e++]);var y=e=>({valueOf:()=>e});s.token.splice(2,0,(e=>116===e&&"true"===i(4)&&p(4)?y(!0):102===e&&"false"===i(5)&&p(5)?y(!1):110===e&&"null"===i(4)&&p(4)?y(null):117===e&&"undefined"===i(9)&&p(9)?y(void 0):null)),s.token[1]=(e,r,t,a)=>{if(34===e||39===e){for(r=i(),p(),a="";(t=u())-e;)92===t?(p(),a+=O[i()]||i()):a+=i(),p();return p(),r+a+r}};var O={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};s.space=e=>{for(;(e=u())<=32;)p(),47===u()&&(42===u(1)?(p(2),p((e=>42!==e&&47!==u(1))),p(2)):47===u(1)&&(p(2),p((e=>e>=32))));return e},s.token.unshift(((e,r)=>123===e&&(p(),r=b(["{",c(0,125)]),p(),r)));var b=(e,r)=>(e[1]?":"==e[1][0]?r=[e[1]]:","==e[1][0]&&(r=e[1].slice(1)):r=[],["{",...r]);for(let e=0,r=[";",1,,"===",9,,"!==",9,,"**",14,,"~",13,-1,"?",3,e=>{let r,t;return e||f("Expected expression"),p(),s.space(),r=c(),58!==u()&&f("Expected :"),p(),s.space(),t=c(),["?:",e,r,t]},"}",,,":",0,,"in",10,e=>u(2)<=32&&[p(2),'"'+e+'"',c(10)],"[",20,(e,r)=>!e&&(p(),r=c(0,93),p(),r?","===r[0]?(r[0]="[",r):["[",r]:["["])];e<r.length;)s.operator(r[e++],r[e++],r[e++]);for(let e=0,t=(["**",(...e)=>e.reduceRight(((e,r)=>Math.pow(r,e))),"~",e=>~e,"?:",(e,r,t)=>e?r:t,"in",(e,r)=>e in r,"[",(...e)=>Array(...e),"{",(...e)=>Object.fromEntries(e),":",(e,r)=>[e,r]]);e<t.length;)r.operator(t[e++],t[e++]);var A=s;export{A as default,r as evaluate,s as parse};
|
package/package.json
CHANGED
package/parse.js
CHANGED
|
@@ -66,7 +66,7 @@ lookup = [],
|
|
|
66
66
|
// @param op is operator string
|
|
67
67
|
// @param prec is operator precedenc to check
|
|
68
68
|
// @param map is either number +1 - postfix unary, -1 prefix unary, 0 binary, else - custom mapper function
|
|
69
|
-
operator = (op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.length, prev=lookup[c], word=op.toUpperCase()!==op, isop) => (
|
|
69
|
+
operator = parse.operator = (op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.length, prev=lookup[c], word=op.toUpperCase()!==op, isop) => (
|
|
70
70
|
isop = l<2 ? // word operator must have space after
|
|
71
71
|
!word ? c=>1 : c=>code(1)<=SPACE :
|
|
72
72
|
!word ? c=>char(l)==op : c=>char(l)==op&&code(l)<=SPACE,
|
package/subscript.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,r,
|
|
1
|
+
var e,r,t=15,a=(t,a)=>(r=t,e=0,a=f(),e<r.length?o():a.valueOf()),o=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},n=(t=1,a=e)=>{if("number"==typeof t)e+=t;else for(;t(l());)e++;return r.slice(a,e)},l=(t=0)=>r.charCodeAt(e+t),s=(t=1)=>r.substr(e,t),f=(e=0,r,t,n,l=0,s,f)=>{for(;(t=a.space())&&(f=i[t]?.(n,e)||!n&&u(t));)n=f;return r&&t!==r&&o("Unclosed paren"),n},p=(a.space=r=>{for(;(r=l())<=32;)e++;return r},a.token=[e=>(e=n((e=>e>47&&e<58||46==e)))&&((69==l()||101==l())&&(e+=n(2)+n((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?o("Bad number"):e),(e,r)=>34==e&&n()+n((r=>r-e))+n(),e=>n((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))]),u=(e,r=0,t)=>{for(;r<p.length;)if(t=p[r++](e))return t},i=[],c=a.operator=(r,t=0,p=0,u,c=r.charCodeAt(0),y=r.length,g=i[c],h=r.toUpperCase()!==r,v)=>(v=y<2?h?e=>l(1)<=32:e=>1:h?e=>s(y)==r&&l(y)<=32:e=>s(y)==r,u=p?p>0?e=>e&&[n(y),e]:p<0?e=>!e&&[n(y),(f(t-1)||o()).valueOf()]:p:n=>{n=[r,n||o()];do{e+=y,n.push((f(t)||o()).valueOf())}while(a.space()==c&&v());return n},i[c]=(e,r)=>r<t&&v()&&u(e)||g&&g(e,r));for(let r=0,a=[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",t,-1,"++",t,-1,"++",t,1,"-",12,,"-",t,-1,"--",t,-1,"--",t,1,"!",t,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[n(),e,"string"==typeof(r=f(18))?'"'+r+'"':r.valueOf()],"[",18,r=>(e++,r=[".",r,f(0,93).valueOf()],e++,r),"]",,,"(",18,(r,t)=>(e++,t=f(0,41),e++,Array.isArray(t)&&","===t[0]?(t[0]=r,t):t?[r,t.valueOf()]:[r]),"(",19,(r,t)=>!r&&(++e,t=f(0,41)||o(),++e,t),")",,,];r<a.length;)c(a[r++],a[r++],a[r++]);var y=a,g=e=>Array.isArray(e)&&("string"==typeof e[0]||g(e[0])),h=(e,r={},t,a)=>g(e)?("string"==typeof(t=e[0])&&(a=v[t]),"function"!=typeof(t=a||h(t,r))?t:t.call(...e.map((e=>h(e,r))))):e&&"string"==typeof e?'"'===e[0]?e.slice(1,-1):"@"===e[0]?e.slice(1):e in r?r[e]:e:e,v={},d=h.operator=(e,r)=>v[e]=2==r.length?(...e)=>e.reduce(r):r;for(let e,r=["!",e=>!e,"++",e=>++e,"--",e=>--e,".",(e,r)=>e&&e[r],"%",(e,r)=>e%r,"/",(e,r)=>e/r,"*",(e,r)=>e*r,"+",(e,r)=>e+r,"-",(...e)=>e.length<2?-e:e.reduce(((e,r)=>e-r)),">>>",(e,r)=>e>>>r,">>",(e,r)=>e>>r,"<<",(e,r)=>e<<r,">=",(e,r)=>e>=r,">",(e,r)=>e>r,"<=",(e,r)=>e<=r,"<",(e,r)=>e<r,"!=",(e,r)=>e!=r,"==",(e,r)=>e==r,"&",(e,r)=>e&r,"^",(e,r)=>e^r,"|",(e,r)=>e|r,"&&",(...e)=>e.every(Boolean),"||",(...e)=>e.some(Boolean),",",(e,r)=>r];e=r.pop();)d(r.pop(),e);var A=h,O=e=>(e="string"==typeof e?y(e):e,r=>A(e,r));export{O as default,A as evaluate,y as parse};
|