subscript 4.0.0 → 5.0.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 +2 -2
- package/evaluate.js +8 -6
- package/justin.js +31 -29
- package/justin.min.js +1 -1
- package/package.json +1 -1
- package/parse.js +108 -94
- package/subscript.min.js +1 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ _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/4.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
33
|
## Operators
|
|
@@ -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: ~200 ms
|
|
283
283
|
jsep: ~280 ms
|
|
284
284
|
expr-eval: ~480 ms
|
|
285
285
|
jexl: ~1200 ms
|
package/evaluate.js
CHANGED
|
@@ -18,6 +18,8 @@ evaluate = (s, ctx={}, c, op) => {
|
|
|
18
18
|
return s
|
|
19
19
|
},
|
|
20
20
|
|
|
21
|
+
reducer=fn=>(...a)=>a.reduce(fn),
|
|
22
|
+
|
|
21
23
|
// op evaluators
|
|
22
24
|
// multiple args allows shortcuts, lisp compatible, easy manual eval, functions anyways take multiple arguments
|
|
23
25
|
operator = evaluate.operator = {
|
|
@@ -25,13 +27,13 @@ operator = evaluate.operator = {
|
|
|
25
27
|
'++':a=>++a,
|
|
26
28
|
'--':a=>--a,
|
|
27
29
|
|
|
28
|
-
'.':(
|
|
30
|
+
'.':reducer((a,b)=>a?a[b]:a),
|
|
29
31
|
|
|
30
|
-
'%':(
|
|
31
|
-
'/':(
|
|
32
|
-
'*':(
|
|
32
|
+
'%':reducer((a,b)=>a%b),
|
|
33
|
+
'/':reducer((a,b)=>a/b),
|
|
34
|
+
'*':reducer((a,b)=>a*b),
|
|
33
35
|
|
|
34
|
-
'+':(
|
|
36
|
+
'+':reducer((a,b)=>a+b),
|
|
35
37
|
'-':(...a)=>a.length < 2 ? -a : a.reduce((a,b)=>a-b),
|
|
36
38
|
|
|
37
39
|
'>>>':(a,b)=>a>>>b,
|
|
@@ -51,7 +53,7 @@ operator = evaluate.operator = {
|
|
|
51
53
|
'|':(a,b)=>a|b,
|
|
52
54
|
'&&':(...a)=>a.every(Boolean),
|
|
53
55
|
'||':(...a)=>a.some(Boolean),
|
|
54
|
-
',':(
|
|
56
|
+
',':reducer((a,b)=>(a,b))
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export default evaluate
|
package/justin.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
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, operator, err} from './parse.js'
|
|
4
4
|
|
|
5
5
|
// ;
|
|
6
|
-
|
|
6
|
+
operator(';', 1)
|
|
7
|
+
|
|
8
|
+
// ===, !==
|
|
9
|
+
operator('===', 9)
|
|
10
|
+
operator('!==', 9)
|
|
7
11
|
|
|
8
12
|
// undefined
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
c ===
|
|
12
|
-
c ===
|
|
13
|
-
c ===
|
|
14
|
-
undefined
|
|
13
|
+
const v = v => ({valueOf:()=>v})
|
|
14
|
+
parse.token.splice(2,0, c =>
|
|
15
|
+
c === 116 && char(4) === 'true' && skip(4) ? v(true) :
|
|
16
|
+
c === 102 && char(5) === 'false' && skip(5) ? v(false) :
|
|
17
|
+
c === 110 && char(4) === 'null' && skip(4) ? v(null) :
|
|
18
|
+
c === 117 && char(9) === 'undefined' && skip(9) ? v(undefined) :
|
|
19
|
+
null
|
|
15
20
|
)
|
|
16
21
|
|
|
17
22
|
// "' with /
|
|
@@ -28,27 +33,25 @@ const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
|
|
|
28
33
|
|
|
29
34
|
// **
|
|
30
35
|
evaluate.operator['**'] = (...args)=>args.reduceRight((a,b)=>Math.pow(b,a))
|
|
31
|
-
|
|
36
|
+
operator('**', 14)
|
|
32
37
|
|
|
33
38
|
// ~
|
|
34
|
-
|
|
39
|
+
operator('~', 13, -1)
|
|
35
40
|
evaluate.operator['~'] = a=>~a
|
|
36
41
|
|
|
37
42
|
// TODO ...
|
|
38
|
-
// // unary[1]['...']=true
|
|
39
|
-
|
|
40
43
|
|
|
41
44
|
// ?:
|
|
42
45
|
evaluate.operator['?:']=(a,b,c)=>a?b:c
|
|
43
|
-
|
|
46
|
+
operator('?', 3, (node) => {
|
|
47
|
+
if (!node) err('Expected expression')
|
|
44
48
|
let a, b
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
skip(), parse.space(), a = expr(-1,58)
|
|
48
|
-
if (code() !== 58) return
|
|
49
|
+
skip(), parse.space(), a = expr()
|
|
50
|
+
if (code() !== 58) err('Expected :')
|
|
49
51
|
skip(), parse.space(), b = expr()
|
|
50
52
|
return ['?:', node, a, b]
|
|
51
53
|
})
|
|
54
|
+
// operator(':')
|
|
52
55
|
|
|
53
56
|
// /**/, //
|
|
54
57
|
parse.space = cc => {
|
|
@@ -65,29 +68,28 @@ parse.space = cc => {
|
|
|
65
68
|
|
|
66
69
|
// in
|
|
67
70
|
evaluate.operator['in'] = (a,b)=>a in b
|
|
68
|
-
|
|
71
|
+
operator('in', 10, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(10)])
|
|
69
72
|
|
|
70
73
|
// []
|
|
71
74
|
evaluate.operator['['] = (...args) => Array(...args)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
skip(), node
|
|
78
|
-
)
|
|
79
|
-
)
|
|
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
80
|
|
|
81
81
|
// {}
|
|
82
82
|
parse.token.unshift((cc, node) => (
|
|
83
|
-
cc === 123
|
|
83
|
+
cc === 123 && (skip(), node = map(['{', expr(0,125)]), skip(), node)
|
|
84
84
|
))
|
|
85
|
-
|
|
85
|
+
|
|
86
|
+
operator('}')
|
|
87
|
+
operator(':', 0)
|
|
86
88
|
evaluate.operator['{'] = (...args)=>Object.fromEntries(args)
|
|
87
89
|
evaluate.operator[':'] = (a,b)=>[a,b]
|
|
88
90
|
|
|
89
91
|
const map = (n, args) => {
|
|
90
|
-
if (n[1]
|
|
92
|
+
if (!n[1]) args = []
|
|
91
93
|
else if (n[1][0]==':') args = [n[1]]
|
|
92
94
|
else if (n[1][0]==',') args = n[1].slice(1)
|
|
93
95
|
return ['{', ...args]
|
package/justin.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,r,
|
|
1
|
+
var e,r,t=e=>Array.isArray(e)&&("string"==typeof e[0]||t(e[0])),a=(e,r={},o,l)=>t(e)?("string"==typeof(o=e[0])&&(l=n[o]),"function"!=typeof(o=l||a(o,r))?o:o.call(...e.map((e=>a(e,r))))):e&&"string"==typeof e?'"'===e[0]?e.slice(1,-1):"@"===e[0]?e.slice(1):e in r?r[e]:e:e,o=e=>(...r)=>r.reduce(e),n=a.operator={"!":e=>!e,"++":e=>++e,"--":e=>--e,".":o(((e,r)=>e&&e[r])),"%":o(((e,r)=>e%r)),"/":o(((e,r)=>e/r)),"*":o(((e,r)=>e*r)),"+":o(((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),",":o(((e,r)=>r))},l=15,s=(t,a)=>(r=t,e=0,a=c(),e<r.length?p():a.valueOf()),p=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},u=(t=1,a=e)=>{if("number"==typeof t)e+=t;else for(;t(f());)e++;return r.slice(a,e)},f=(t=0)=>r.charCodeAt(e+t),i=(t=1)=>r.substr(e,t),c=(e=0,r,t,a,o=0,n,l)=>{for(;(t=s.space())&&(l=h[t]?.(a,e)||!a&&d(t));)a=l;return r&&t!==r&&p("Unclosed paren"),a},v=(s.space=r=>{for(;(r=f())<=32;)e++;return r},s.token=[e=>(e=u((e=>e>47&&e<58||46==e)))&&((69==f()||101==f())&&(e+=u(2)+u((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?p("Bad number"):e),(e,r)=>34==e&&u()+u((r=>r-e))+u(),e=>u((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))]),d=(e,r=0,t)=>{for(;r<v.length;)if(t=v[r++](e))return t},h=[],y=(r,t=0,a=0,o,n=r.charCodeAt(0),l=r.length,v=h[n],d=r.toUpperCase()!==r,y)=>(y=l<2?d?e=>f(1)<=32:e=>1:d?e=>i(l)==r&&f(l)<=32:e=>i(l)==r,o=a?a>0?e=>e&&[u(l),e]:a<0?e=>!e&&[u(l),(c(t-1)||p()).valueOf()]:a:a=>{a=[r,a||p()];do{e+=l,a.push((c(t)||p()).valueOf())}while(s.space()==n&&y());return a},h[n]=(e,r)=>r<t&&y()&&o(e)||v&&v(e,r));for(let r=0,t=[",",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&&[u(),e,"string"==typeof(r=c(18))?'"'+r+'"':r.valueOf()],"[",18,r=>(e++,r=[".",r,c(0,93).valueOf()],e++,r),"]",,,"(",18,(r,t)=>(e++,t=c(0,41),e++,Array.isArray(t)&&","===t[0]?(t[0]=r,t):t?[r,t.valueOf()]:[r]),"(",19,(r,t)=>!r&&(++e,t=c(0,41)||p(),++e,t),")",,,];r<t.length;)y(t[r++],t[r++],t[r++]);y(";",1),y("===",9),y("!==",9);var g=e=>({valueOf:()=>e});s.token.splice(2,0,(e=>116===e&&"true"===i(4)&&u(4)?g(!0):102===e&&"false"===i(5)&&u(5)?g(!1):110===e&&"null"===i(4)&&u(4)?g(null):117===e&&"undefined"===i(9)&&u(9)?g(void 0):null)),s.token[1]=(e,r,t,a)=>{if(34===e||39===e){for(r=i(),u(),a="";(t=f())-e;)92===t?(u(),a+=O[i()]||i()):a+=i(),u();return u(),r+a+r}};var O={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};a.operator["**"]=(...e)=>e.reduceRight(((e,r)=>Math.pow(r,e))),y("**",14),y("~",13,-1),a.operator["~"]=e=>~e,a.operator["?:"]=(e,r,t)=>e?r:t,y("?",3,(e=>{let r,t;return e||p("Expected expression"),u(),s.space(),r=c(),58!==f()&&p("Expected :"),u(),s.space(),t=c(),["?:",e,r,t]})),s.space=e=>{for(;(e=f())<=32;)u(),47===f()&&(42===f(1)?(u(2),u((e=>42!==e&&47!==f(1))),u(2)):47===f(1)&&(u(2),u((e=>e>=32))));return e},a.operator.in=(e,r)=>e in r,y("in",10,(e=>f(2)<=32&&[u(2),'"'+e+'"',c(10)])),a.operator["["]=(...e)=>Array(...e),y("[",20,((e,r)=>!e&&(u(),r=c(0,93),u(),r?","===r[0]?(r[0]="[",r):["[",r]:["["]))),s.token.unshift(((e,r)=>123===e&&(u(),r=b(["{",c(0,125)]),u(),r))),y("}"),y(":",0),a.operator["{"]=(...e)=>Object.fromEntries(e),a.operator[":"]=(e,r)=>[e,r];var b=(e,r)=>(e[1]?":"==e[1][0]?r=[e[1]]:","==e[1][0]&&(r=e[1].slice(1)):r=[],["{",...r]),A=s;export{A as default,a as evaluate,s as parse};
|
package/package.json
CHANGED
package/parse.js
CHANGED
|
@@ -1,39 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
|
|
2
|
+
|
|
3
|
+
PREC_SEQ=1, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
|
|
4
|
+
PREC_EQ=9, PREC_COMP=10, PREC_SHIFT=11, PREC_SUM=12, PREC_MULT=13, PREC_UNARY=15, PREC_POSTFIX=16, PREC_CALL=18, PREC_GROUP=19
|
|
5
|
+
|
|
3
6
|
|
|
4
7
|
// current string & index
|
|
5
8
|
let idx, cur
|
|
6
9
|
|
|
7
|
-
export const parse = (str, tree) => (cur=str, idx=0, tree=expr(), idx<cur.length ? err() : tree),
|
|
10
|
+
export const parse = (str, tree) => (cur=str, idx=0, tree=expr(), idx<cur.length ? err() : tree.valueOf()),
|
|
8
11
|
|
|
9
12
|
err = (msg='Bad syntax') => { throw Error(msg + ' `' + cur[idx] + '` at ' + idx) },
|
|
10
13
|
|
|
11
14
|
skip = (is=1, from=idx) => {
|
|
12
15
|
if (typeof is === 'number') idx += is
|
|
13
16
|
else while (is(code())) idx++;
|
|
14
|
-
return cur.slice(from, idx)
|
|
17
|
+
return cur.slice(from, idx)
|
|
15
18
|
},
|
|
16
19
|
|
|
17
20
|
code = (i=0) => cur.charCodeAt(idx+i),
|
|
18
21
|
|
|
19
22
|
char = (n=1) => cur.substr(idx, n),
|
|
20
23
|
|
|
21
|
-
nil = '',
|
|
22
|
-
|
|
23
24
|
// a + b - c
|
|
24
|
-
expr = (prec=0, end, cc
|
|
25
|
-
//
|
|
26
|
-
while (
|
|
25
|
+
expr = (prec=0, end, cc, node, i=0, map, newNode) => {
|
|
26
|
+
// chunk/token parser
|
|
27
|
+
while (
|
|
28
|
+
(cc=parse.space()) && (newNode = lookup[cc]?.(node, prec) || (!node && token(cc)) )
|
|
29
|
+
) node = newNode;
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
for (i = Math.max(lookup[cc=parse.space()]|0, prec); i < parse.operator.length;) {
|
|
30
|
-
if (cc===end || i<prec) break // if lookup got prec lower than current - end group
|
|
31
|
-
else if (mapped = parse.operator[i++](node, cc, i, end))
|
|
32
|
-
mapped.indexOf(nil) >=0 && err('Bad expression'),
|
|
33
|
-
node = mapped, i = Math.max(lookup[cc=parse.space()]|0, prec); // we pass i+1 as precision
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!prec && end && code()!=end) err('Unclosed paren')
|
|
31
|
+
if (end && cc !== end) err('Unclosed paren')
|
|
37
32
|
|
|
38
33
|
return node
|
|
39
34
|
},
|
|
@@ -42,20 +37,17 @@ expr = (prec=0, end, cc=parse.space(), node, from=idx, i=0, mapped) => {
|
|
|
42
37
|
space = parse.space = cc => { while (cc = code(), cc <= SPACE) idx++; return cc },
|
|
43
38
|
|
|
44
39
|
// tokens
|
|
45
|
-
|
|
40
|
+
tokens = parse.token = [
|
|
46
41
|
// 1.2e+3, .5 - fast & small version, but consumes corrupted nums as well
|
|
47
|
-
(number) =>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
},
|
|
42
|
+
(number) => (
|
|
43
|
+
(number = skip(c => (c > 47 && c < 58) || c == PERIOD)) && (
|
|
44
|
+
(code() == 69 || code() == 101) && (number += skip(2) + skip(c => c >= 48 && c <= 57)),
|
|
45
|
+
isNaN(number = new Number(number)) ? err('Bad number') : number
|
|
46
|
+
)
|
|
47
|
+
),
|
|
54
48
|
// "a"
|
|
55
|
-
(q, qc) => q
|
|
56
|
-
//
|
|
57
|
-
c => c === OPAREN ? (++idx, c=expr(0,CPAREN), ++idx, c===nil?err():c) : nil,
|
|
58
|
-
// var
|
|
49
|
+
(q, qc) => q == 34 && (skip() + skip(c => c-q) + skip()),
|
|
50
|
+
// id
|
|
59
51
|
c => skip(c =>
|
|
60
52
|
(c >= 48 && c <= 57) || // 0..9
|
|
61
53
|
(c >= 65 && c <= 90) || // A...Z
|
|
@@ -65,70 +57,92 @@ token = parse.token = [
|
|
|
65
57
|
)
|
|
66
58
|
],
|
|
67
59
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
60
|
+
token = (c,i=0,node) => { while(i<tokens.length) if (node = tokens[i++](c)) return node },
|
|
61
|
+
|
|
62
|
+
// operator lookup table
|
|
63
|
+
lookup = [],
|
|
64
|
+
|
|
65
|
+
// create operator checker/mapper (see examples)
|
|
66
|
+
// @param op is operator string
|
|
67
|
+
// @param prec is operator precedenc to check
|
|
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) => (
|
|
70
|
+
isop = l<2 ? // word operator must have space after
|
|
71
|
+
!word ? c=>1 : c=>code(1)<=SPACE :
|
|
72
|
+
!word ? c=>char(l)==op : c=>char(l)==op&&code(l)<=SPACE,
|
|
73
|
+
|
|
74
|
+
map = !type ? node => { // binary, consume same-op group
|
|
75
|
+
node = [op, node || err()]
|
|
76
|
+
// in order to support literal tokens, we call valueOf any time we create or modify calltree node
|
|
77
|
+
do { idx+=l, node.push((expr(prec) || err()).valueOf()) } while (parse.space()==c && isop())
|
|
78
|
+
return node
|
|
79
|
+
} :
|
|
80
|
+
type > 0 ? node => node && [skip(l), node] : // postfix unary
|
|
81
|
+
type < 0 ? node => !node && [skip(l), (expr(prec-1) || err()).valueOf()] : // prefix unary
|
|
82
|
+
type,
|
|
83
|
+
|
|
84
|
+
lookup[c] = (node, curPrec) => curPrec < prec && isop() && map(node) || (prev && prev(node, curPrec))
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
// ,
|
|
88
|
+
for (let i = 0, ops = [
|
|
89
|
+
// TODO: add ,, as node here
|
|
90
|
+
',', PREC_SEQ,,
|
|
91
|
+
|
|
92
|
+
'|', PREC_OR,,
|
|
93
|
+
'||', PREC_SOME,,
|
|
94
|
+
|
|
95
|
+
'&', PREC_AND,,
|
|
96
|
+
'&&', PREC_EVERY,,
|
|
97
|
+
|
|
98
|
+
'^', PREC_XOR,,
|
|
99
|
+
|
|
100
|
+
// ==, !=
|
|
101
|
+
'==', PREC_EQ,,
|
|
102
|
+
'!=', PREC_EQ,,
|
|
103
|
+
|
|
104
|
+
// > >= >> >>>, < <= <<
|
|
105
|
+
'>', PREC_COMP,,
|
|
106
|
+
'>=', PREC_COMP,,
|
|
107
|
+
'>>', PREC_SHIFT,,
|
|
108
|
+
'>>>', PREC_SHIFT,,
|
|
109
|
+
'<', PREC_COMP,,
|
|
110
|
+
'<=', PREC_COMP,,
|
|
111
|
+
'<<', PREC_SHIFT,,
|
|
112
|
+
|
|
113
|
+
// + ++ - --
|
|
114
|
+
'+', PREC_SUM,,
|
|
115
|
+
'+', PREC_UNARY, -1,
|
|
116
|
+
'++', PREC_UNARY, -1,
|
|
117
|
+
'++', PREC_UNARY, +1,
|
|
118
|
+
'-', PREC_SUM,,
|
|
119
|
+
'-', PREC_UNARY, -1,
|
|
120
|
+
'--', PREC_UNARY, -1,
|
|
121
|
+
'--', PREC_UNARY, +1,
|
|
122
|
+
|
|
123
|
+
// ! ~
|
|
124
|
+
'!', PREC_UNARY, -1,
|
|
125
|
+
|
|
126
|
+
// * / %
|
|
127
|
+
'*', PREC_MULT,,
|
|
128
|
+
'/', PREC_MULT,,
|
|
129
|
+
'%', PREC_MULT,,
|
|
130
|
+
|
|
131
|
+
// a.b
|
|
132
|
+
'.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
|
|
133
|
+
|
|
134
|
+
// a[b]
|
|
135
|
+
'[', PREC_CALL, (node) => (idx++, node = ['.', node, expr(0,CBRACK).valueOf()], idx++, node),
|
|
136
|
+
']',,,
|
|
137
|
+
|
|
138
|
+
// a(b)
|
|
139
|
+
'(', PREC_CALL, (node,b) => ( idx++, b=expr(0,CPAREN), idx++,
|
|
140
|
+
Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, b.valueOf()] : [node]
|
|
141
|
+
),
|
|
142
|
+
// (a+b)
|
|
143
|
+
'(', PREC_GROUP, (node,b) => !node && (++idx, b=expr(0,CPAREN) || err(), ++idx, b),
|
|
144
|
+
')',,,
|
|
145
|
+
]; i < ops.length;) operator(ops[i++],ops[i++],ops[i++])
|
|
132
146
|
|
|
133
147
|
|
|
134
148
|
export default parse
|
package/subscript.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,r,a=(a,
|
|
1
|
+
var e,r,a=15,t=(a,t)=>(r=a,e=0,t=f(),e<r.length?o():t.valueOf()),o=(a="Bad syntax")=>{throw Error(a+" `"+r[e]+"` at "+e)},n=(a=1,t=e)=>{if("number"==typeof a)e+=a;else for(;a(s());)e++;return r.slice(t,e)},s=(a=0)=>r.charCodeAt(e+a),l=(a=1)=>r.substr(e,a),f=(e=0,r,a,n,s=0,l,f)=>{for(;(a=t.space())&&(f=i[a]?.(n,e)||!n&&p(a));)n=f;return r&&a!==r&&o("Unclosed paren"),n},u=(t.space=r=>{for(;(r=s())<=32;)e++;return r},t.token=[e=>(e=n((e=>e>47&&e<58||46==e)))&&((69==s()||101==s())&&(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))]),p=(e,r=0,a)=>{for(;r<u.length;)if(a=u[r++](e))return a},i=[],c=(r,a=0,u=0,p,c=r.charCodeAt(0),y=r.length,g=i[c],h=r.toUpperCase()!==r,v)=>(v=y<2?h?e=>s(1)<=32:e=>1:h?e=>l(y)==r&&s(y)<=32:e=>l(y)==r,p=u?u>0?e=>e&&[n(y),e]:u<0?e=>!e&&[n(y),(f(a-1)||o()).valueOf()]:u:n=>{n=[r,n||o()];do{e+=y,n.push((f(a)||o()).valueOf())}while(t.space()==c&&v());return n},i[c]=(e,r)=>r<a&&v()&&p(e)||g&&g(e,r));for(let r=0,t=[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",a,-1,"++",a,-1,"++",a,1,"-",12,,"-",a,-1,"--",a,-1,"--",a,1,"!",a,-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,a)=>(e++,a=f(0,41),e++,Array.isArray(a)&&","===a[0]?(a[0]=r,a):a?[r,a.valueOf()]:[r]),"(",19,(r,a)=>!r&&(++e,a=f(0,41)||o(),++e,a),")",,,];r<t.length;)c(t[r++],t[r++],t[r++]);var y=t,g=e=>Array.isArray(e)&&("string"==typeof e[0]||g(e[0])),h=(e,r={},a,t)=>g(e)?("string"==typeof(a=e[0])&&(t=d[a]),"function"!=typeof(a=t||h(a,r))?a:a.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=e=>(...r)=>r.reduce(e),d=h.operator={"!":e=>!e,"++":e=>++e,"--":e=>--e,".":v(((e,r)=>e&&e[r])),"%":v(((e,r)=>e%r)),"/":v(((e,r)=>e/r)),"*":v(((e,r)=>e*r)),"+":v(((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),",":v(((e,r)=>r))},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};
|