subscript 7.4.3 → 7.4.5

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 CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  _Subscript_ is expression evaluator / microlanguage with [common syntax](https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)) (JavaScript, Java, C, C++, Rust, Go, Python, Kotlin etc).<br/>
4
4
 
5
- * Tiny size <sub><a href="https://bundlephobia.com/package/subscript@6.0.0"><img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/subscript/latest?color=brightgreen&label=gzip"/></a></sub>
5
+ * Tiny size <sub><a href="https://bundlephobia.com/package/subscript"><img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/subscript/latest?color=brightgreen&label=gzip"/></a></sub>
6
6
  * :rocket: Fast [performance](#performance)
7
7
  * Configurable & extensible
8
8
  * Trivial to use
9
9
 
10
10
  ```js
11
- import createFn, { parse, compile } from './subscript.js'
11
+ import subscript, { parse, compile } from './subscript.js'
12
12
 
13
13
  // create expression evaluator
14
- let fn = createFn('a.b + c(d - 1)')
14
+ let fn = subscript('a.b + c(d - 1)')
15
15
  fn({ a: { b:1 }, c: x => x * 2, d: 3 }) // 5
16
16
 
17
17
  // or
@@ -21,7 +21,7 @@ tree // ['+', ['.', 'a', 'b'], 'c']
21
21
 
22
22
  // compile tree to evaluable function
23
23
  fn = compile(tree)
24
- fn({a:{b:1}, c:2}) // 3
24
+ fn({a:{b:1}, c:2}) // 3
25
25
  ```
26
26
 
27
27
  ## Motivation
@@ -33,12 +33,13 @@ _Subscript_ is designed to be useful for:
33
33
  * configurable subsets of languages (eg. [justin](#justin))
34
34
  * pluggable/mock language features (eg. pipe operator)
35
35
  * sandboxes, playgrounds, safe eval
36
- * custom DSL <!-- see sonr, mineural -->
36
+ * custom DSL (see [lino](https://github.com/dy/lino)) <!-- uneural -->
37
+ * preprocessors (see [prepr](https://github.com/dy/prepr))
37
38
 
38
- _Subscript_ has [2.8kb](https://npmfs.com/package/subscript/7.0.0/subscript.min.js) footprint, compared to [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_ + [4.5kb](https://npmfs.com/package/expression-eval/5.0.0/dist/expression-eval.module.js) _expression-eval_, with better test coverage and better performance.
39
+ _Subscript_ has [3.5kb](https://npmfs.com/package/subscript/7.4.3/subscript.min.js) footprint, compared to [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_ + [4.5kb](https://npmfs.com/package/expression-eval/5.0.0/dist/expression-eval.module.js) _expression-eval_, with better test coverage and better performance.
39
40
 
40
41
 
41
- ## Operators
42
+ ## Operators / literals
42
43
 
43
44
  <small>↑ precedence order</small>
44
45
 
@@ -57,12 +58,38 @@ _Subscript_ has [2.8kb](https://npmfs.com/package/subscript/7.0.0/subscript.min.
57
58
  * `a && b`
58
59
  * `a || b`
59
60
  * `a , b`
60
-
61
- ## Literals
62
-
63
61
  * `"abc"` strings
64
62
  * `1.2e+3` numbers
65
63
 
64
+ ## Justin
65
+
66
+ _Justin_ is minimal JS subset − JSON with JS expressions (see original [thread](https://github.com/endojs/Jessie/issues/66)).<br/>
67
+
68
+ It extends _subscript_ with:
69
+
70
+ + `===`, `!==` operators
71
+ + `**` exponentiation operator (right-assoc)
72
+ + `~` bit inversion operator
73
+ + `'` strings
74
+ + `?:` ternary operator
75
+ + `?.` optional chain operator
76
+ + `??` nullish coalesce operator
77
+ + `[...]` Array literal
78
+ + `{...}` Object literal
79
+ + `in` binary
80
+ + `;` expression separator
81
+ + `//`, `/* */` comments
82
+ + `true`, `false`, `null`, `undefined` literals
83
+ <!-- + `...x` unary operator -->
84
+ <!-- + strings interpolation -->
85
+
86
+ ```js
87
+ import jstin from 'subscript/justin.js'
88
+
89
+ let xy = jstin('{ x: 1, "y": 2+2 }["x"]')
90
+ xy() // 1
91
+ ```
92
+
66
93
  ## Extending
67
94
 
68
95
  Operators/tokens can be extended via:
@@ -70,7 +97,7 @@ Operators/tokens can be extended via:
70
97
  * `unary(str, precedence, postfix=false)` − register unary operator, either prefix or postfix.
71
98
  * `binary(str, precedence, rightAssoc=false)` − register binary operator, optionally right-associative.
72
99
  * `nary(str, precedence, allowSkip=false)` − register n-ary (sequence) operator, optionally allowing skipping args.
73
- * `token(str, precedence, map)` − register custom token or literal. `map` takes last token argument and returns calltree node.
100
+ * `token(str, precedence, map)` − register custom token or literal. `map` takes last token argument and returns tree node.
74
101
  * `operator(str, fn)` − register evaluator for operator. `fn` takes node arguments and returns evaluator function.
75
102
 
76
103
  ```js
@@ -97,13 +124,13 @@ See [subscript.js](subscript.js) or [justin.js](./justin.js) for examples.
97
124
 
98
125
  Subscript exposes separate `./parse.js` and `./compile.js` entries. Parser builds AST, compiler converts it to evaluable function.
99
126
 
100
- AST has simplified lispy calltree structure (inspired by [frisk](https://ghub.io/frisk) / [nisp](https://github.com/ysmood/nisp)), opposed to [ESTree](https://github.com/estree/estree):
127
+ AST has simplified lispy tree structure (inspired by [frisk](https://ghub.io/frisk) / [nisp](https://github.com/ysmood/nisp)), opposed to [ESTree](https://github.com/estree/estree):
101
128
 
102
- * is not limited to particular language, can be compiled to different targets;
129
+ * not limited to particular language (JS), can be compiled to different targets;
103
130
  * reflects execution sequence, rather than code layout;
104
- * has minimal possible overhead, directly maps to operators;
131
+ * has minimal possible overhead (object wrappers, named properties), directly maps to operators;
105
132
  * simplifies manual evaluation and debugging;
106
- * has conventional form and one-liner docs:
133
+ * has conventional form and one-line docs:
107
134
 
108
135
  ```js
109
136
  import { compile } from 'subscript.js'
@@ -113,35 +140,6 @@ const fn = compile(['+', ['*', 'min', ['',60]], ['','sec']])
113
140
  fn({min: 5}) // min*60 + "sec" == "300sec"
114
141
  ```
115
142
 
116
- ## Justin
117
-
118
- _Justin_ is minimal JS subset − JSON with JS expressions (see original [thread](https://github.com/endojs/Jessie/issues/66)).<br/>
119
-
120
- It extends _subscript_ with:
121
-
122
- + `===`, `!==` operators
123
- + `**` exponentiation operator (right-assoc)
124
- + `~` bit inversion operator
125
- + `'` strings
126
- + `?:` ternary operator
127
- + `?.` optional chain operator
128
- + `??` nullish coalesce operator
129
- + `[...]` Array literal
130
- + `{...}` Object literal
131
- + `in` binary
132
- + `;` expression separator
133
- + `//`, `/* */` comments
134
- + `true`, `false`, `null`, `undefined` literals
135
- <!-- + `...x` unary operator -->
136
- <!-- + strings interpolation -->
137
-
138
- ```js
139
- import jstin from 'subscript/justin.js'
140
-
141
- let xy = jstin('{ x: 1, "y": 2+2 }["x"]')
142
- xy() // 1
143
- ```
144
-
145
143
  <!--
146
144
  ## Ideas
147
145
 
package/justin.min.js CHANGED
@@ -1 +1 @@
1
- let e,t,r=r=>(e=0,t=r,r=s(),t[e]?l():r||""),l=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{throw SyntaxError(`${r} ${l?`\`${l}\` `:""}at ${n.length}:${a.length}`,n.length)},n=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{let s=t.slice(e-10,e).split("\n").pop(),i=t.slice(e+1,e+10).split("\n").shift(),h=n.length+":"+a.length;throw EvalError(`${r} at ${h} \`${s+l+i}\`\n${" ".repeat(18+r.length+h.length+s.length+1)}^`)},a=(r=1,l=e,n)=>{if("number"==typeof r)e+=r;else for(;n=r(t.charCodeAt(e));)e+=n;return t.slice(l,e)},s=(t=0,n,a,s,i,h)=>{for(;(a=r.space())&&(i=((h=o[a])&&h(s,t))??(!s&&r.id()));)s=i;return n&&(a==n?e++:l()),s},i=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,h=r.space=r=>{for(;(r=t.charCodeAt(e))<=32;)e++;return r},p=r.id=e=>a(i),o=[],c=(r,l=32,n,a=r.charCodeAt(0),s=r.length,h=o[a],p=r.toUpperCase()!==r)=>o[a]=(a,o,c=e)=>o<l&&(s<2||t.substr(e,s)==r)&&(!p||!i(t.charCodeAt(e+s)))&&(e+=s,n(a,o))||(e=c,h?.(a,o)),f=(e,t,r=0)=>c(e,t,((l,n)=>l&&(n=s(t-r/2))&&[e,l,n])),g=(e,t,r)=>c(e,t,(l=>r?l&&[e,l]:!l&&(l=s(t-1))&&[e,l])),d=(e,t,r)=>c(e,t,((l,n)=>(l||r&&(l=[e]))&&((n=s(t))||r)&&(!(l[0]===e&&l[2])&&(l=[e,l]),n&&l.push(n),l)));const u=e=>Array.isArray(e)?m[e[0]](...e.slice(1)):t=>t?.[e],m={},A=(e,t,r=m[e])=>m[e]=(...e)=>t(...e)||r&&r(...e),b=e=>(e=r(e),t=>(e.call?e:e=u(e))(t)),y=(e,t,r)=>r[0]||r[1]?(t?c(e,t,r[0]):o[e.charCodeAt(0)||1]=r[0],A(e,r[1])):r.length?r.length>1?(f(e,Math.abs(t),t<0),A(e,((e,t)=>t&&(e=u(e),t=u(t),e.length||t.length?l=>r(e(l),t(l)):(e=r(e(),t()),()=>e))))):(g(e,t),A(e,((e,t)=>!t&&((e=u(e)).length?t=>r(e(t)):(e=r(e()),()=>e))))):(d(e,Math.abs(t),t<0),A(e,((...e)=>(e=e.map(u),t=>r(...e.map((e=>e(t)))))))),$=e=>e?l():["",(e=+a((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?l():e],C=(e,t,r,l)=>[e,t,[r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,s(t-1)],l=(e,t)=>"("===e[0]?l(e[1]):"."===e[0]?(t=e[2],e=u(e[1]),l=>r(e(l),t)):"["===e[0]?([,e,t]=e,e=u(e),t=u(t),l=>r(e(l),t(l))):t=>r(t,e)]],x=["",,[,e=>()=>e],'"',,[e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)]],".",,[e=>!e&&$()],...Array(10).fill(0).flatMap(((e,t)=>[""+t,0,[$]])),",",1,(...e)=>e[e.length-1],"||",4,(...e)=>{let t,r=0;for(;!t&&r<e.length;)t=e[r++];return t},"&&",5,(...e)=>{let t=0,r=!0;for(;r&&t<e.length;)r=e[t++];return r},"+",12,(e,t)=>e+t,"-",12,(e,t)=>e-t,"*",13,(e,t)=>e*t,"/",13,(e,t)=>e/t,"%",13,(e,t)=>e%t,"|",6,(e,t)=>e|t,"&",8,(e,t)=>e&t,"^",7,(e,t)=>e^t,"==",9,(e,t)=>e==t,"!=",9,(e,t)=>e!=t,">",10,(e,t)=>e>t,">=",10,(e,t)=>e>=t,"<",10,(e,t)=>e<t,"<=",10,(e,t)=>e<=t,">>",11,(e,t)=>e>>t,">>>",11,(e,t)=>e>>>t,"<<",11,(e,t)=>e<<t,"+",15,e=>+e,"-",15,e=>-e,"!",15,e=>!e,...C("++",15,((e,t)=>++e[t])),...C("--",15,((e,t)=>--e[t])),"[",18,[e=>e&&["[",e,s(0,93)||l()],(e,t)=>t&&(e=u(e),t=u(t),r=>e(r)[t(r)])],".",18,[(e,t)=>e&&(t=s(18))&&[".",e,t],(e,t)=>(e=u(e),t=t[0]?t:t[1],r=>e(r)[t])],"(",18,[e=>!e&&["(",s(0,41)||l()],u],"(",18,[(e,t)=>e&&((t=s(0,41))?["(",e,t]:["(",e,""]),(e,t,r,l)=>null!=t&&(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(u),e=>t.map((t=>t(e)))):(t=u(t),e=>[t(e)]),"."===e[0]?(r=e[2],e=u(e[1]),t=>e(t)[r](...l(t))):"["===e[0]?(r=u(e[2]),e=u(e[1]),t=>e(t)[r(t)](...l(t))):(e=u(e),t=>e(t)(...l(t))))]];for(;x[2];)y(...x.splice(0,3));let E={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},v=r=>(n,s,i="")=>{for(n&&l("Unexpected string"),a();(s=t.charCodeAt(e))-r;)92===s?(a(),s=a(),i+=E[s]||s):i+=a();return a(),["",i]},B=["===",9,(e,t)=>e===t,"!==",9,(e,t)=>e!==t,"~",15,e=>~e,"?",3,[(e,t,r)=>e&&(t=s(2,58))&&["?",e,t,s(3)],(e,t,r)=>(e=u(e),t=u(t),r=u(r),l=>e(l)?t(l):r(l))],"??",6,(e,t)=>e??t,"?.",18,[e=>e&&["?.",e],e=>(e=u(e),t=>e(t)||(()=>{}))],"?.",18,[(e,t)=>e&&!(t=s(18))?.map&&["?.",e,t],(e,t)=>t&&(e=u(e),r=>e(r)?.[t])],"in",10,(e,t)=>e in t,'"',,[v(34)],"'",,[v(39)],"/*",20,[(r,l)=>(a((r=>42!==r&&47!==t.charCodeAt(e+1))),a(2),r||s(l))],"//",20,[(e,t)=>(a((e=>e>=32)),e||s(t))],"null",20,[e=>e?l():["",null]],"true",20,[e=>e?l():["",!0]],"false",20,[e=>e?l():["",!1]],"undefined",20,[e=>e?l():["",void 0]],";",-20,(...e)=>{for(let t=e.length;t--;)if(null!=e[t])return e[t]},"**",-14,(e,t)=>e**t,"[",20,[e=>!e&&["[",s(0,93)||""],(e,t)=>!t&&(e?","===e[0]?(e=e.slice(1).map(u),t=>e.map((e=>e(t)))):(e=u(e),t=>[e(t)]):()=>[])],"{",20,[e=>!e&&["{",s(0,125)||""],(e,t)=>e?","===e[0]?(e=e.slice(1).map(u),t=>Object.fromEntries(e.map((e=>e(t))))):":"===e[0]?(e=u(e),t=>Object.fromEntries([e(t)])):(t=u(e),r=>({[e]:t(r)})):e=>({})],":",1.1,[(e,t)=>[":",e,s(1.1)||l()],(e,t)=>(t=u(t),e=Array.isArray(e)?u(e):(e=>e).bind(0,e),r=>[e(r),t(r)])]];for(;B[2];)y(...B.splice(0,3));export{f as binary,u as compile,t as cur,b as default,l as err,s as expr,p as id,e as idx,i as isId,n as longErr,o as lookup,d as nary,A as operator,m as operators,r as parse,y as set,a as skip,h as space,c as token,g as unary};
1
+ let e,t,r=r=>(e=0,t=r,r=s(),t[e]?l():r||""),l=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{throw SyntaxError(`${r} ${l?`\`${l}\` `:""}at ${n.length}:${a.length}`,n.length)},n=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{let s=t.slice(e-10,e).split("\n").pop(),i=t.slice(e+1,e+10).split("\n").shift(),h=n.length+":"+a.length;throw EvalError(`${r} at ${h} \`${s+l+i}\`\n${" ".repeat(18+r.length+h.length+s.length+1)}^`)},a=(r=1,l=e,n)=>{if("number"==typeof r)e+=r;else for(;n=r(t.charCodeAt(e));)e+=n;return t.slice(l,e)},s=(t=0,n,a,s,i,h)=>{for(;(a=r.space())&&(i=((h=o[a])&&h(s,t))??(!s&&r.id()));)s=i;return n&&(a==n?e++:l()),s},i=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,h=r.space=r=>{for(;(r=t.charCodeAt(e))<=32;)e++;return r},p=r.id=e=>a(i),o=[],c=(r,l=32,n,a=r.charCodeAt(0),s=r.length,h=o[a],p=r.toUpperCase()!==r)=>o[a]=(a,o,c=e)=>o<l&&(s<2||t.substr(e,s)==r)&&(!p||!i(t.charCodeAt(e+s)))&&(e+=s,n(a,o))||(e=c,h?.(a,o)),f=(e,t,r=0)=>c(e,t,((l,n)=>l&&(n=s(t-r/2))&&[e,l,n])),g=(e,t,r)=>c(e,t,(l=>r?l&&[e,l]:!l&&(l=s(t-1))&&[e,l])),d=(e,t,r)=>{c(e,t,((l,n)=>(l||r)&&((n=s(t))||r)&&((!l||l[0]!==e)&&(l=[e,l]),(n||r)&&l.push(n),l)))};const u=e=>Array.isArray(e)?m[e[0]](...e.slice(1)):t=>t?.[e],m={},A=(e,t,r=m[e])=>m[e]=(...e)=>t(...e)||r&&r(...e),b=e=>(e=r(e),t=>(e.call?e:e=u(e))(t)),y=(e,t,r)=>r[0]||r[1]?(t?c(e,t,r[0]):o[e.charCodeAt(0)||1]=r[0],A(e,r[1])):r.length?r.length>1?(f(e,Math.abs(t),t<0),A(e,((e,t)=>t&&(e=u(e),t=u(t),e.length||t.length?l=>r(e(l),t(l)):(e=r(e(),t()),()=>e))))):(g(e,t),A(e,((e,t)=>!t&&((e=u(e)).length?t=>r(e(t)):(e=r(e()),()=>e))))):(d(e,Math.abs(t),t<0),A(e,((...e)=>(e=e.map(u),t=>r(...e.map((e=>e(t)))))))),$=e=>e?l():["",(e=+a((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?l():e],C=(e,t,r,l)=>[e,t,[r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,s(t-1)],l=(e,t)=>"("===e[0]?l(e[1]):"."===e[0]?(t=e[2],e=u(e[1]),l=>r(e(l),t)):"["===e[0]?([,e,t]=e,e=u(e),t=u(t),l=>r(e(l),t(l))):t=>r(t,e)]],x=["",,[,e=>()=>e],'"',,[e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)]],".",,[e=>!e&&$()],...Array(10).fill(0).flatMap(((e,t)=>[""+t,0,[$]])),",",1,(...e)=>e[e.length-1],"||",4,(...e)=>{let t,r=0;for(;!t&&r<e.length;)t=e[r++];return t},"&&",5,(...e)=>{let t=0,r=!0;for(;r&&t<e.length;)r=e[t++];return r},"+",12,(e,t)=>e+t,"-",12,(e,t)=>e-t,"*",13,(e,t)=>e*t,"/",13,(e,t)=>e/t,"%",13,(e,t)=>e%t,"|",6,(e,t)=>e|t,"&",8,(e,t)=>e&t,"^",7,(e,t)=>e^t,"==",9,(e,t)=>e==t,"!=",9,(e,t)=>e!=t,">",10,(e,t)=>e>t,">=",10,(e,t)=>e>=t,"<",10,(e,t)=>e<t,"<=",10,(e,t)=>e<=t,">>",11,(e,t)=>e>>t,">>>",11,(e,t)=>e>>>t,"<<",11,(e,t)=>e<<t,"+",15,e=>+e,"-",15,e=>-e,"!",15,e=>!e,...C("++",15,((e,t)=>++e[t])),...C("--",15,((e,t)=>--e[t])),"[",18,[e=>e&&["[",e,s(0,93)||l()],(e,t)=>t&&(e=u(e),t=u(t),r=>e(r)[t(r)])],".",18,[(e,t)=>e&&(t=s(18))&&[".",e,t],(e,t)=>(e=u(e),t=t[0]?t:t[1],r=>e(r)[t])],"(",18,[e=>!e&&["(",s(0,41)||l()],u],"(",18,[(e,t)=>e&&((t=s(0,41))?["(",e,t]:["(",e,""]),(e,t,r,l)=>null!=t&&(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(u),e=>t.map((t=>t(e)))):(t=u(t),e=>[t(e)]),"."===e[0]?(r=e[2],e=u(e[1]),t=>e(t)[r](...l(t))):"["===e[0]?(r=u(e[2]),e=u(e[1]),t=>e(t)[r(t)](...l(t))):(e=u(e),t=>e(t)(...l(t))))]];for(;x[2];)y(...x.splice(0,3));let E={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},v=r=>(n,s,i="")=>{for(n&&l("Unexpected string"),a();(s=t.charCodeAt(e))-r;)92===s?(a(),s=a(),i+=E[s]||s):i+=a();return a(),["",i]},B=["===",9,(e,t)=>e===t,"!==",9,(e,t)=>e!==t,"~",15,e=>~e,"?",3,[(e,t,r)=>e&&(t=s(2,58))&&["?",e,t,s(3)],(e,t,r)=>(e=u(e),t=u(t),r=u(r),l=>e(l)?t(l):r(l))],"??",6,(e,t)=>e??t,"?.",18,[e=>e&&["?.",e],e=>(e=u(e),t=>e(t)||(()=>{}))],"?.",18,[(e,t)=>e&&!(t=s(18))?.map&&["?.",e,t],(e,t)=>t&&(e=u(e),r=>e(r)?.[t])],"in",10,(e,t)=>e in t,'"',,[v(34)],"'",,[v(39)],"/*",20,[(r,l)=>(a((r=>42!==r&&47!==t.charCodeAt(e+1))),a(2),r||s(l))],"//",20,[(e,t)=>(a((e=>e>=32)),e||s(t))],"null",20,[e=>e?l():["",null]],"true",20,[e=>e?l():["",!0]],"false",20,[e=>e?l():["",!1]],"undefined",20,[e=>e?l():["",void 0]],";",-20,(...e)=>{for(let t=e.length;t--;)if(null!=e[t])return e[t]},"**",-14,(e,t)=>e**t,"[",20,[e=>!e&&["[",s(0,93)||""],(e,t)=>!t&&(e?","===e[0]?(e=e.slice(1).map(u),t=>e.map((e=>e(t)))):(e=u(e),t=>[e(t)]):()=>[])],"{",20,[e=>!e&&["{",s(0,125)||""],(e,t)=>e?","===e[0]?(e=e.slice(1).map(u),t=>Object.fromEntries(e.map((e=>e(t))))):":"===e[0]?(e=u(e),t=>Object.fromEntries([e(t)])):(t=u(e),r=>({[e]:t(r)})):e=>({})],":",1.1,[(e,t)=>[":",e,s(1.1)||l()],(e,t)=>(t=u(t),e=Array.isArray(e)?u(e):(e=>e).bind(0,e),r=>[e(r),t(r)])]];for(;B[2];)y(...B.splice(0,3));export{f as binary,u as compile,t as cur,b as default,l as err,s as expr,p as id,e as idx,i as isId,n as longErr,o as lookup,d as nary,A as operator,m as operators,r as parse,y as set,a as skip,h as space,c as token,g as unary};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "subscript",
3
- "version": "7.4.3",
4
- "description": "Fast and tiny expression evaluator with common syntax microlanguage.",
3
+ "version": "7.4.5",
4
+ "description": "Fast and tiny expression evaluator with minimal syntax.",
5
5
  "main": "subscript.js",
6
6
  "module": "subscript.js",
7
7
  "browser": "subscript.js",
@@ -34,7 +34,7 @@
34
34
  "min-subscript": "terser subscript.min.js -o subscript.min.js --module -c passes=3 -m",
35
35
  "build-justin": "rollup justin.js --file justin.min.js --format esm --name \"Justin\"",
36
36
  "min-justin": "terser justin.min.js -o justin.min.js --module -c passes=3 -m",
37
- "test": "node test && node test/jsep && node test/perf",
37
+ "test": "node test/tree && node test/subscript && node test/jsep && node test/perf",
38
38
  "check-types": "tsc --noEmit subscript.d.ts"
39
39
  },
40
40
  "repository": {
package/parse.js CHANGED
@@ -80,6 +80,16 @@ token = (
80
80
  // right assoc is indicated by negative precedence (meaning go from right to left)
81
81
  binary = (op, prec, right=0) => token(op, prec, (a, b) => a && (b=expr(prec-right/2)) && [op,a,b] ),
82
82
  unary = (op, prec, post) => token(op, prec, a => post ? (a && [op, a]) : (!a && (a=expr(prec-1)) && [op, a])),
83
- nary = (op, prec, skips) => token(op, prec, (a, b) => (a || (skips && (a=[op]))) && (b=expr(prec),b||skips) && (!(a[0] === op && a[2]) && (a = [op,a]), b && a.push(b), a))
83
+ nary = (op, prec, skips) => {
84
+ token(op, prec, (a, b) => (
85
+ (a || skips) && // if lhs exists or we're ok to skip
86
+ (b=expr(prec), b||skips) && // either rhs exists or we're ok to skip rhs
87
+ (
88
+ (!a || a[0] !== op) && (a = [op,a]), // if beginning of sequence - init node
89
+ (b || skips) && a.push(b),
90
+ a
91
+ ))
92
+ )
93
+ }
84
94
 
85
95
  export default parse
package/subscript.min.js CHANGED
@@ -1 +1 @@
1
- let t,e,l=l=>(t=0,e=l,l=s(),e[t]?r():l||""),r=(l="Bad syntax",r=e[t],a=e.slice(0,t).split("\n"),n=a.pop())=>{throw SyntaxError(`${l} ${r?`\`${r}\` `:""}at ${a.length}:${n.length}`,a.length)},a=(l="Bad syntax",r=e[t],a=e.slice(0,t).split("\n"),n=a.pop())=>{let s=e.slice(t-10,t).split("\n").pop(),h=e.slice(t+1,t+10).split("\n").shift(),p=a.length+":"+n.length;throw EvalError(`${l} at ${p} \`${s+r+h}\`\n${" ".repeat(18+l.length+p.length+s.length+1)}^`)},n=(l=1,r=t,a)=>{if("number"==typeof l)t+=l;else for(;a=l(e.charCodeAt(t));)t+=a;return e.slice(r,t)},s=(e=0,a,n,s,h,p)=>{for(;(n=l.space())&&(h=((p=i[n])&&p(s,e))??(!s&&l.id()));)s=h;return a&&(n==a?t++:r()),s},h=t=>t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122||36==t||95==t||t>=192&&215!=t&&247!=t,p=l.space=l=>{for(;(l=e.charCodeAt(t))<=32;)t++;return l},o=l.id=t=>n(h),i=[],c=(l,r=32,a,n=l.charCodeAt(0),s=l.length,p=i[n],o=l.toUpperCase()!==l)=>i[n]=(n,i,c=t)=>i<r&&(s<2||e.substr(t,s)==l)&&(!o||!h(e.charCodeAt(t+s)))&&(t+=s,a(n,i))||(t=c,p?.(n,i)),g=(t,e,l=0)=>c(t,e,((r,a)=>r&&(a=s(e-l/2))&&[t,r,a])),f=(t,e,l)=>c(t,e,(r=>l?r&&[t,r]:!r&&(r=s(e-1))&&[t,r])),d=(t,e,l)=>c(t,e,((r,a)=>(r||l&&(r=[t]))&&((a=s(e))||l)&&(!(r[0]===t&&r[2])&&(r=[t,r]),a&&r.push(a),r)));const u=t=>Array.isArray(t)?$[t[0]](...t.slice(1)):e=>e?.[t],$={},A=(t,e,l=$[t])=>$[t]=(...t)=>e(...t)||l&&l(...t),y=t=>(t=l(t),e=>(t.call?t:t=u(t))(e)),C=(t,e,l)=>l[0]||l[1]?(e?c(t,e,l[0]):i[t.charCodeAt(0)||1]=l[0],A(t,l[1])):l.length?l.length>1?(g(t,Math.abs(e),e<0),A(t,((t,e)=>e&&(t=u(t),e=u(e),t.length||e.length?r=>l(t(r),e(r)):(t=l(t(),e()),()=>t))))):(f(t,e),A(t,((t,e)=>!e&&((t=u(t)).length?e=>l(t(e)):(t=l(t()),()=>t))))):(d(t,Math.abs(e),e<0),A(t,((...t)=>(t=t.map(u),e=>l(...t.map((t=>t(e)))))))),m=t=>t?r():["",(t=+n((t=>46===t||t>=48&&t<=57||(69===t||101===t?2:0))))!=t?r():t],b=(t,e,l,r)=>[t,e,[l=>l?["++"===t?"-":"+",[t,l],["",1]]:[t,s(e-1)],r=(t,e)=>"("===t[0]?r(t[1]):"."===t[0]?(e=t[2],t=u(t[1]),r=>l(t(r),e)):"["===t[0]?([,t,e]=t,t=u(t),e=u(e),r=>l(t(r),e(r))):e=>l(e,t)]],x=["",,[,t=>()=>t],'"',,[t=>t?r():["",(n()+n((t=>t-34?1:0))+(n()||r("Bad string"))).slice(1,-1)]],".",,[t=>!t&&m()],...Array(10).fill(0).flatMap(((t,e)=>[""+e,0,[m]])),",",1,(...t)=>t[t.length-1],"||",4,(...t)=>{let e,l=0;for(;!e&&l<t.length;)e=t[l++];return e},"&&",5,(...t)=>{let e=0,l=!0;for(;l&&e<t.length;)l=t[e++];return l},"+",12,(t,e)=>t+e,"-",12,(t,e)=>t-e,"*",13,(t,e)=>t*e,"/",13,(t,e)=>t/e,"%",13,(t,e)=>t%e,"|",6,(t,e)=>t|e,"&",8,(t,e)=>t&e,"^",7,(t,e)=>t^e,"==",9,(t,e)=>t==e,"!=",9,(t,e)=>t!=e,">",10,(t,e)=>t>e,">=",10,(t,e)=>t>=e,"<",10,(t,e)=>t<e,"<=",10,(t,e)=>t<=e,">>",11,(t,e)=>t>>e,">>>",11,(t,e)=>t>>>e,"<<",11,(t,e)=>t<<e,"+",15,t=>+t,"-",15,t=>-t,"!",15,t=>!t,...b("++",15,((t,e)=>++t[e])),...b("--",15,((t,e)=>--t[e])),"[",18,[t=>t&&["[",t,s(0,93)||r()],(t,e)=>e&&(t=u(t),e=u(e),l=>t(l)[e(l)])],".",18,[(t,e)=>t&&(e=s(18))&&[".",t,e],(t,e)=>(t=u(t),e=e[0]?e:e[1],l=>t(l)[e])],"(",18,[t=>!t&&["(",s(0,41)||r()],u],"(",18,[(t,e)=>t&&((e=s(0,41))?["(",t,e]:["(",t,""]),(t,e,l,r)=>null!=e&&(r=""==e?()=>[]:","===e[0]?(e=e.slice(1).map(u),t=>e.map((e=>e(t)))):(e=u(e),t=>[e(t)]),"."===t[0]?(l=t[2],t=u(t[1]),e=>t(e)[l](...r(e))):"["===t[0]?(l=u(t[2]),t=u(t[1]),e=>t(e)[l(e)](...r(e))):(t=u(t),e=>t(e)(...r(e))))]];for(;x[2];)C(...x.splice(0,3));export{g as binary,u as compile,e as cur,y as default,r as err,s as expr,o as id,t as idx,h as isId,a as longErr,i as lookup,d as nary,A as operator,$ as operators,l as parse,C as set,n as skip,p as space,c as token,f as unary};
1
+ let t,e,l=l=>(t=0,e=l,l=s(),e[t]?r():l||""),r=(l="Bad syntax",r=e[t],a=e.slice(0,t).split("\n"),n=a.pop())=>{throw SyntaxError(`${l} ${r?`\`${r}\` `:""}at ${a.length}:${n.length}`,a.length)},a=(l="Bad syntax",r=e[t],a=e.slice(0,t).split("\n"),n=a.pop())=>{let s=e.slice(t-10,t).split("\n").pop(),h=e.slice(t+1,t+10).split("\n").shift(),p=a.length+":"+n.length;throw EvalError(`${l} at ${p} \`${s+r+h}\`\n${" ".repeat(18+l.length+p.length+s.length+1)}^`)},n=(l=1,r=t,a)=>{if("number"==typeof l)t+=l;else for(;a=l(e.charCodeAt(t));)t+=a;return e.slice(r,t)},s=(e=0,a,n,s,h,p)=>{for(;(n=l.space())&&(h=((p=i[n])&&p(s,e))??(!s&&l.id()));)s=h;return a&&(n==a?t++:r()),s},h=t=>t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122||36==t||95==t||t>=192&&215!=t&&247!=t,p=l.space=l=>{for(;(l=e.charCodeAt(t))<=32;)t++;return l},o=l.id=t=>n(h),i=[],c=(l,r=32,a,n=l.charCodeAt(0),s=l.length,p=i[n],o=l.toUpperCase()!==l)=>i[n]=(n,i,c=t)=>i<r&&(s<2||e.substr(t,s)==l)&&(!o||!h(e.charCodeAt(t+s)))&&(t+=s,a(n,i))||(t=c,p?.(n,i)),g=(t,e,l=0)=>c(t,e,((r,a)=>r&&(a=s(e-l/2))&&[t,r,a])),f=(t,e,l)=>c(t,e,(r=>l?r&&[t,r]:!r&&(r=s(e-1))&&[t,r])),d=(t,e,l)=>{c(t,e,((r,a)=>(r||l)&&((a=s(e))||l)&&((!r||r[0]!==t)&&(r=[t,r]),(a||l)&&r.push(a),r)))};const u=t=>Array.isArray(t)?$[t[0]](...t.slice(1)):e=>e?.[t],$={},A=(t,e,l=$[t])=>$[t]=(...t)=>e(...t)||l&&l(...t),y=t=>(t=l(t),e=>(t.call?t:t=u(t))(e)),C=(t,e,l)=>l[0]||l[1]?(e?c(t,e,l[0]):i[t.charCodeAt(0)||1]=l[0],A(t,l[1])):l.length?l.length>1?(g(t,Math.abs(e),e<0),A(t,((t,e)=>e&&(t=u(t),e=u(e),t.length||e.length?r=>l(t(r),e(r)):(t=l(t(),e()),()=>t))))):(f(t,e),A(t,((t,e)=>!e&&((t=u(t)).length?e=>l(t(e)):(t=l(t()),()=>t))))):(d(t,Math.abs(e),e<0),A(t,((...t)=>(t=t.map(u),e=>l(...t.map((t=>t(e)))))))),m=t=>t?r():["",(t=+n((t=>46===t||t>=48&&t<=57||(69===t||101===t?2:0))))!=t?r():t],b=(t,e,l,r)=>[t,e,[l=>l?["++"===t?"-":"+",[t,l],["",1]]:[t,s(e-1)],r=(t,e)=>"("===t[0]?r(t[1]):"."===t[0]?(e=t[2],t=u(t[1]),r=>l(t(r),e)):"["===t[0]?([,t,e]=t,t=u(t),e=u(e),r=>l(t(r),e(r))):e=>l(e,t)]],x=["",,[,t=>()=>t],'"',,[t=>t?r():["",(n()+n((t=>t-34?1:0))+(n()||r("Bad string"))).slice(1,-1)]],".",,[t=>!t&&m()],...Array(10).fill(0).flatMap(((t,e)=>[""+e,0,[m]])),",",1,(...t)=>t[t.length-1],"||",4,(...t)=>{let e,l=0;for(;!e&&l<t.length;)e=t[l++];return e},"&&",5,(...t)=>{let e=0,l=!0;for(;l&&e<t.length;)l=t[e++];return l},"+",12,(t,e)=>t+e,"-",12,(t,e)=>t-e,"*",13,(t,e)=>t*e,"/",13,(t,e)=>t/e,"%",13,(t,e)=>t%e,"|",6,(t,e)=>t|e,"&",8,(t,e)=>t&e,"^",7,(t,e)=>t^e,"==",9,(t,e)=>t==e,"!=",9,(t,e)=>t!=e,">",10,(t,e)=>t>e,">=",10,(t,e)=>t>=e,"<",10,(t,e)=>t<e,"<=",10,(t,e)=>t<=e,">>",11,(t,e)=>t>>e,">>>",11,(t,e)=>t>>>e,"<<",11,(t,e)=>t<<e,"+",15,t=>+t,"-",15,t=>-t,"!",15,t=>!t,...b("++",15,((t,e)=>++t[e])),...b("--",15,((t,e)=>--t[e])),"[",18,[t=>t&&["[",t,s(0,93)||r()],(t,e)=>e&&(t=u(t),e=u(e),l=>t(l)[e(l)])],".",18,[(t,e)=>t&&(e=s(18))&&[".",t,e],(t,e)=>(t=u(t),e=e[0]?e:e[1],l=>t(l)[e])],"(",18,[t=>!t&&["(",s(0,41)||r()],u],"(",18,[(t,e)=>t&&((e=s(0,41))?["(",t,e]:["(",t,""]),(t,e,l,r)=>null!=e&&(r=""==e?()=>[]:","===e[0]?(e=e.slice(1).map(u),t=>e.map((e=>e(t)))):(e=u(e),t=>[e(t)]),"."===t[0]?(l=t[2],t=u(t[1]),e=>t(e)[l](...r(e))):"["===t[0]?(l=u(t[2]),t=u(t[1]),e=>t(e)[l(e)](...r(e))):(t=u(t),e=>t(e)(...r(e))))]];for(;x[2];)C(...x.splice(0,3));export{g as binary,u as compile,e as cur,y as default,r as err,s as expr,o as id,t as idx,h as isId,a as longErr,i as lookup,d as nary,A as operator,$ as operators,l as parse,C as set,n as skip,p as space,c as token,f as unary};