subscript 7.1.1 → 7.2.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 CHANGED
@@ -62,26 +62,37 @@ Default literals:
62
62
  * `"abc"` strings
63
63
  * `1.2e+3` numbers
64
64
 
65
- Everything else can be extended via `subscript.set(str, prec, fn)` for unary, binary or n-ary operators (detected by number of arguments in `fn`), or via `subscript.set(str, prec, [parse, compile])` for custom tokens.
65
+ ## Extending
66
+
67
+ Operators/tokens can be extended via:
68
+
69
+ * `unary(str, prec, postfix=false)` − register unary operator, either prefix or postfix.
70
+ * `binary(str, prec, rightAssoc=false)` − register binary operator, optionally right-associative.
71
+ * `nary(str, prec)` − register n-ary (sequence) operator.
72
+ * `token(str, prec, fn)` − register custom token or literal. `fn` takes last token as argument and returns calltree node.
73
+ * `operator(str, fn)` − register evaluator for operator. `fn` takes node arguments and returns evaluator function.
66
74
 
67
75
  ```js
68
- import script, { compile } from './subscript.js'
76
+ import script, { operator, unary, binary, token } from './subscript.js'
69
77
 
70
78
  // add ~ unary operator with precedence 15
71
- script.set('~', 15, a => ~a)
79
+ unary('~', 15)
80
+ operator('~', a => ~a)
72
81
 
73
82
  // add === binary operator with precedence 9
74
- script.set('===', 9, (a, b) => a===b)
83
+ binary('===', 9)
84
+ operator('===', (a, b) => a===b)
75
85
 
76
86
  // add literals
77
- script.set('true', 20, [a => ['',true], a => ctx => a[1]])
78
- script.set('false', 20, [a => ['',false], a => ctx => a[1]])
87
+ token('true', 20, a => ['',true])
88
+ token('false', 20, a => ['',false])
89
+ operator('', a => ctx => a[1]])
79
90
  ```
80
91
 
81
92
  See [subscript.js](subscript.js) or [justin.js](./justin.js) for examples.
82
93
 
83
94
 
84
- ## Parser & Compiler
95
+ ## Syntax tree
85
96
 
86
97
  Subscript exposes separate `./parse.js` and `./compile.js` entries. Parser builds AST, compiler converts it to evaluable function.
87
98
 
package/compile.js CHANGED
@@ -1,13 +1,8 @@
1
1
  // build optimized evaluator for the tree
2
- export const compile = (node) => !Array.isArray(node) ? ctx => ctx?.[node] : operator[node[0]](...node.slice(1))
2
+ export const compile = (node) => !Array.isArray(node) ? ctx => ctx?.[node] : operators[node[0]](...node.slice(1)),
3
3
 
4
- const operator = {}
4
+ operators = {},
5
5
 
6
- compile.set = (op, fn, prev=operator[op]) => operator[op] = (...args) => fn(...args) || prev && prev(...args)
7
- compile.binary = (op, fn) => compile.set(op,
8
- (a,b) => b && (a=compile(a),b=compile(b), !a.length&&!b.length ? (a=fn(a(),b()),()=>a) : ctx => fn(a(ctx),b(ctx)))
9
- )
10
- compile.unary = (op, fn) => compile.set(op, (a,b) => !b && (a=compile(a), !a.length ? (a=fn(a()),()=>a) : ctx => fn(a(ctx))))
11
- compile.nary = (op, fn) => compile.set(op, (...args) => (args=args.map(compile), ctx => fn(...args.map(arg=>arg(ctx)))))
6
+ operator = (op, fn, prev=operators[op]) => operators[op] = (...args) => fn(...args) || prev && prev(...args)
12
7
 
13
8
  export default compile
package/justin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // justin lang https://github.com/endojs/Jessie/issues/66
2
2
  import { skip, cur, idx, err, expr } from './parse.js'
3
3
  import compile from './compile.js'
4
- import subscript from './subscript.js'
4
+ import subscript, { set } from './subscript.js'
5
5
 
6
6
  const PERIOD=46, OPAREN=40, CPAREN=41, OBRACK=91, CBRACK=93, SPACE=32, DQUOTE=34, QUOTE=39, _0=48, _9=57, BSLASH=92,
7
7
  PREC_SEQ=1, PREC_COND=3, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
@@ -88,7 +88,7 @@ list = [
88
88
  (a,b) => (b=compile(b),a=Array.isArray(a)?compile(a):(a=>a).bind(0,a), ctx=>[a(ctx),b(ctx)])
89
89
  ]
90
90
  ]
91
- for (;list[2];) subscript.set(...list.splice(0,3))
91
+ for (;list[2];) set(...list.splice(0,3))
92
92
 
93
93
  export default subscript
94
94
  export * from './subscript.js'
package/justin.min.js CHANGED
@@ -1 +1 @@
1
- let e,r,t=t=>(e=0,r=t,t=s(),r[e]?n():t||""),n=(t="Bad syntax",n=r[e],a=r.slice(0,e).split("\n"),s=a.pop())=>{throw SyntaxError(`${t} \`${n}\` at ${a.length}:${s.length}`)},a=(t=1,n=e,a)=>{if("number"==typeof t)e+=t;else for(;a=t(r.charCodeAt(e));)e+=a;return r.slice(n,e)},s=(r=0,a,s,l,o,c)=>{for(;(s=t.space())&&(o=((c=i[s])&&c(l,r))??(!l&&t.id()));)l=o;return a&&(s==a?e++:n()),l},l=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e;t.space=t=>{for(;(t=r.charCodeAt(e))<=32;)e++;return t},t.id=e=>a(l);let i=[];t.set=(t,n=32,a,s=t.charCodeAt(0),o=t.length,c=i[s],p=t.toUpperCase()!==t)=>i[s]=(s,i,h=e)=>i<n&&(o<2||r.substr(e,o)==t)&&(!p||!l(r.charCodeAt(e+o)))&&(e+=o,a(s,i))||(e=h,c?.(s,i)),t.binary=(e,r,n)=>t.set(e,r,((t,a)=>t&&(a=s(r-!!n))&&[e,t,a])),t.unary=(e,r,n)=>t.set(e,r,(t=>!t&&(t=s(r-1))&&[e,t])),t.nary=(e,r)=>t.set(e,r,((t,n)=>t&&(n=s(r))&&(t[0]===e&&t[2]?(t.push(n),t):[e,t,n])));const o=e=>Array.isArray(e)?c[e[0]](...e.slice(1)):r=>r?.[e],c={};o.set=(e,r,t=c[e])=>c[e]=(...e)=>r(...e)||t&&t(...e),o.binary=(e,r)=>o.set(e,((e,t)=>t&&(e=o(e),t=o(t),e.length||t.length?n=>r(e(n),t(n)):(e=r(e(),t()),()=>e)))),o.unary=(e,r)=>o.set(e,((e,t)=>!t&&((e=o(e)).length?t=>r(e(t)):(e=r(e()),()=>e)))),o.nary=(e,r)=>o.set(e,((...e)=>(e=e.map(o),t=>r(...e.map((e=>e(t)))))));const p=e=>(e=t(e),r=>(e.call?e:e=o(e))(r)),h=p.set=(e,r,n)=>n[0]||n[1]?(r?t.set(e,r,n[0]):i[e.charCodeAt(0)||1]=n[0],o.set(e,n[1])):n.length?n.length>1?(t.binary(e,Math.abs(r),r<0),o.binary(e,n)):(t.unary(e,r),o.unary(e,n)):(t.nary(e,r),o.nary(e,n)),y=e=>e?n():["",(e=+a((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?n():e],f=(e,r,t,n)=>[e,r,[t=>t?["++"===e?"-":"+",[e,t],["",1]]:[e,s(r-1)],n=(e,r)=>"("===e[0]?n(e[1]):"."===e[0]?(r=e[2],e=o(e[1]),n=>t(e(n),r)):"["===e[0]?([,e,r]=e,e=o(e),r=o(r),n=>t(e(n),r(n))):r=>t(r,e)]],u=["",,[,e=>()=>e],'"',,[e=>e?n():["",(a()+a((e=>e-34?1:0))+(a()||n("Bad string"))).slice(1,-1)]],".",,[e=>!e&&y()],...Array(10).fill(0).flatMap(((e,r)=>[""+r,0,[y]])),",",1,(...e)=>e[e.length-1],"||",4,(...e)=>{let r,t=0;for(;!r&&t<e.length;)r=e[t++];return r},"&&",5,(...e)=>{let r=0,t=!0;for(;t&&r<e.length;)t=e[r++];return t},"+",12,(e,r)=>e+r,"-",12,(e,r)=>e-r,"*",13,(e,r)=>e*r,"/",13,(e,r)=>e/r,"%",13,(e,r)=>e%r,"|",6,(e,r)=>e|r,"&",8,(e,r)=>e&r,"^",7,(e,r)=>e^r,"==",9,(e,r)=>e==r,"!=",9,(e,r)=>e!=r,">",10,(e,r)=>e>r,">=",10,(e,r)=>e>=r,"<",10,(e,r)=>e<r,"<=",10,(e,r)=>e<=r,">>",11,(e,r)=>e>>r,">>>",11,(e,r)=>e>>>r,"<<",11,(e,r)=>e<<r,"+",15,e=>+e,"-",15,e=>-e,"!",15,e=>!e,...f("++",15,((e,r)=>++e[r])),...f("--",15,((e,r)=>--e[r])),"[",18,[e=>e&&["[",e,s(0,93)||n()],(e,r)=>r&&(e=o(e),r=o(r),t=>e(t)[r(t)])],".",18,[(e,r)=>e&&(r=s(18))&&[".",e,r],(e,r)=>(e=o(e),r=r[0]?r:r[1],t=>e(t)[r])],"(",18,[e=>!e&&["(",s(0,41)||n()],o],"(",18,[e=>e&&["(",e,s(0,41)||""],(e,r,t,n)=>null!=r&&(n=""==r?()=>[]:","===r[0]?(r=r.slice(1).map(o),e=>r.map((r=>r(e)))):(r=o(r),e=>[r(e)]),"."===e[0]?(t=e[2],e=o(e[1]),r=>e(r)[t](...n(r))):"["===e[0]?(t=o(e[2]),e=o(e[1]),r=>e(r)[t(r)](...n(r))):(e=o(e),r=>e(r)(...n(r))))]];for(;u[2];)h(...u.splice(0,3));let d={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},g=t=>(s,l,i="")=>{for(s&&n("Unexpected string"),a();(l=r.charCodeAt(e))-t;)92===l?(a(),l=a(),i+=d[l]||l):i+=a();return a(),["",i]},b=["===",9,(e,r)=>e===r,"!==",9,(e,r)=>e!==r,"~",15,e=>~e,"?",3,[(e,r,t)=>e&&(r=s(2,58))&&["?",e,r,s(3)],(e,r,t)=>(e=o(e),r=o(r),t=o(t),n=>e(n)?r(n):t(n))],"??",6,(e,r)=>e??r,"?.",18,[e=>e&&["?.",e],e=>(e=o(e),r=>e(r)||(()=>{}))],"?.",18,[(e,r)=>e&&!(r=s(18))?.map&&["?.",e,r],(e,r)=>r&&(e=o(e),t=>e(t)?.[r])],"in",10,(e,r)=>e in r,'"',,[g(34)],"'",,[g(39)],"/*",20,[(t,n)=>(a((t=>42!==t&&47!==r.charCodeAt(e+1))),a(2),t||s(n))],"//",20,[(e,r)=>(a((e=>e>=32)),e||s(r))],"null",20,[e=>e?n():["",null]],"true",20,[e=>e?n():["",!0]],"false",20,[e=>e?n():["",!1]],"undefined",20,[e=>e?n():["",void 0]],";",20,[e=>s()||[""]],"**",-14,(e,r)=>e**r,"[",20,[e=>!e&&["[",s(0,93)||""],(e,r)=>!r&&(e?","===e[0]?(e=e.slice(1).map(o),r=>e.map((e=>e(r)))):(e=o(e),r=>[e(r)]):()=>[])],"{",20,[e=>!e&&["{",s(0,125)||""],(e,r)=>e?","===e[0]?(e=e.slice(1).map(o),r=>Object.fromEntries(e.map((e=>e(r))))):":"===e[0]?(e=o(e),r=>Object.fromEntries([e(r)])):(r=o(e),t=>({[e]:r(t)})):e=>({})],":",1.1,[(e,r)=>[":",e,s(1.1)||n()],(e,r)=>(r=o(r),e=Array.isArray(e)?o(e):(e=>e).bind(0,e),t=>[e(t),r(t)])]];for(;b[2];)p.set(...b.splice(0,3));export{o as compile,p as default,t as parse};
1
+ let e,r,t=t=>(e=0,r=t,t=n(),r[e]?l():t||""),l=(t="Bad syntax",l=r[e],a=r.slice(0,e).split("\n"),n=a.pop())=>{throw SyntaxError(`${t} \`${l}\` at ${a.length}:${n.length}`)},a=(t=1,l=e,a)=>{if("number"==typeof t)e+=t;else for(;a=t(r.charCodeAt(e));)e+=a;return r.slice(l,e)},n=(r=0,a,n,s,i,o)=>{for(;(n=t.space())&&(i=((o=c[n])&&o(s,r))??(!s&&t.id()));)s=i;return a&&(n==a?e++:l()),s},s=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,i=t.space=t=>{for(;(t=r.charCodeAt(e))<=32;)e++;return t},o=t.id=e=>a(s),c=[],p=(t,l=32,a,n=t.charCodeAt(0),i=t.length,o=c[n],p=t.toUpperCase()!==t)=>c[n]=(n,c,h=e)=>c<l&&(i<2||r.substr(e,i)==t)&&(!p||!s(r.charCodeAt(e+i)))&&(e+=i,a(n,c))||(e=h,o?.(n,c)),h=(e,r,t)=>p(e,r,((l,a)=>l&&(a=n(r-!!t))&&[e,l,a])),f=(e,r,t)=>p(e,r,(l=>t?l&&[e,l]:!l&&(l=n(r-1))&&[e,l])),d=(e,r)=>p(e,r,((t,l)=>t&&(l=n(r))&&(t[0]===e&&t[2]?(t.push(l),t):[e,t,l])));const u=e=>Array.isArray(e)?g[e[0]](...e.slice(1)):r=>r?.[e],g={},m=(e,r,t=g[e])=>g[e]=(...e)=>r(...e)||t&&t(...e),A=e=>(e=t(e),r=>(e.call?e:e=u(e))(r)),b=(e,r,t)=>t[0]||t[1]?(r?p(e,r,t[0]):c[e.charCodeAt(0)||1]=t[0],m(e,t[1])):t.length?t.length>1?(h(e,Math.abs(r),r<0),m(e,((e,r)=>r&&(e=u(e),r=u(r),e.length||r.length?l=>t(e(l),r(l)):(e=t(e(),r()),()=>e))))):(f(e,r),m(e,((e,r)=>!r&&((e=u(e)).length?r=>t(e(r)):(e=t(e()),()=>e))))):(d(e,r),m(e,((...e)=>(e=e.map(u),r=>t(...e.map((e=>e(r)))))))),y=e=>e?l():["",(e=+a((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?l():e],C=(e,r,t,l)=>[e,r,[t=>t?["++"===e?"-":"+",[e,t],["",1]]:[e,n(r-1)],l=(e,r)=>"("===e[0]?l(e[1]):"."===e[0]?(r=e[2],e=u(e[1]),l=>t(e(l),r)):"["===e[0]?([,e,r]=e,e=u(e),r=u(r),l=>t(e(l),r(l))):r=>t(r,e)]],x=["",,[,e=>()=>e],'"',,[e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)]],".",,[e=>!e&&y()],...Array(10).fill(0).flatMap(((e,r)=>[""+r,0,[y]])),",",1,(...e)=>e[e.length-1],"||",4,(...e)=>{let r,t=0;for(;!r&&t<e.length;)r=e[t++];return r},"&&",5,(...e)=>{let r=0,t=!0;for(;t&&r<e.length;)t=e[r++];return t},"+",12,(e,r)=>e+r,"-",12,(e,r)=>e-r,"*",13,(e,r)=>e*r,"/",13,(e,r)=>e/r,"%",13,(e,r)=>e%r,"|",6,(e,r)=>e|r,"&",8,(e,r)=>e&r,"^",7,(e,r)=>e^r,"==",9,(e,r)=>e==r,"!=",9,(e,r)=>e!=r,">",10,(e,r)=>e>r,">=",10,(e,r)=>e>=r,"<",10,(e,r)=>e<r,"<=",10,(e,r)=>e<=r,">>",11,(e,r)=>e>>r,">>>",11,(e,r)=>e>>>r,"<<",11,(e,r)=>e<<r,"+",15,e=>+e,"-",15,e=>-e,"!",15,e=>!e,...C("++",15,((e,r)=>++e[r])),...C("--",15,((e,r)=>--e[r])),"[",18,[e=>e&&["[",e,n(0,93)||l()],(e,r)=>r&&(e=u(e),r=u(r),t=>e(t)[r(t)])],".",18,[(e,r)=>e&&(r=n(18))&&[".",e,r],(e,r)=>(e=u(e),r=r[0]?r:r[1],t=>e(t)[r])],"(",18,[e=>!e&&["(",n(0,41)||l()],u],"(",18,[e=>e&&["(",e,n(0,41)||""],(e,r,t,l)=>null!=r&&(l=""==r?()=>[]:","===r[0]?(r=r.slice(1).map(u),e=>r.map((r=>r(e)))):(r=u(r),e=>[r(e)]),"."===e[0]?(t=e[2],e=u(e[1]),r=>e(r)[t](...l(r))):"["===e[0]?(t=u(e[2]),e=u(e[1]),r=>e(r)[t(r)](...l(r))):(e=u(e),r=>e(r)(...l(r))))]];for(;x[2];)b(...x.splice(0,3));let $={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},v=t=>(n,s,i="")=>{for(n&&l("Unexpected string"),a();(s=r.charCodeAt(e))-t;)92===s?(a(),s=a(),i+=$[s]||s):i+=a();return a(),["",i]},E=["===",9,(e,r)=>e===r,"!==",9,(e,r)=>e!==r,"~",15,e=>~e,"?",3,[(e,r,t)=>e&&(r=n(2,58))&&["?",e,r,n(3)],(e,r,t)=>(e=u(e),r=u(r),t=u(t),l=>e(l)?r(l):t(l))],"??",6,(e,r)=>e??r,"?.",18,[e=>e&&["?.",e],e=>(e=u(e),r=>e(r)||(()=>{}))],"?.",18,[(e,r)=>e&&!(r=n(18))?.map&&["?.",e,r],(e,r)=>r&&(e=u(e),t=>e(t)?.[r])],"in",10,(e,r)=>e in r,'"',,[v(34)],"'",,[v(39)],"/*",20,[(t,l)=>(a((t=>42!==t&&47!==r.charCodeAt(e+1))),a(2),t||n(l))],"//",20,[(e,r)=>(a((e=>e>=32)),e||n(r))],"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=>n()||[""]],"**",-14,(e,r)=>e**r,"[",20,[e=>!e&&["[",n(0,93)||""],(e,r)=>!r&&(e?","===e[0]?(e=e.slice(1).map(u),r=>e.map((e=>e(r)))):(e=u(e),r=>[e(r)]):()=>[])],"{",20,[e=>!e&&["{",n(0,125)||""],(e,r)=>e?","===e[0]?(e=e.slice(1).map(u),r=>Object.fromEntries(e.map((e=>e(r))))):":"===e[0]?(e=u(e),r=>Object.fromEntries([e(r)])):(r=u(e),t=>({[e]:r(t)})):e=>({})],":",1.1,[(e,r)=>[":",e,n(1.1)||l()],(e,r)=>(r=u(r),e=Array.isArray(e)?u(e):(e=>e).bind(0,e),t=>[e(t),r(t)])]];for(;E[2];)b(...E.splice(0,3));export{h as binary,u as compile,r as cur,A as default,l as err,n as expr,o as id,e as idx,s as isId,c as lookup,d as nary,m as operator,g as operators,t as parse,b as set,a as skip,i as space,p as token,f as unary};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subscript",
3
- "version": "7.1.1",
3
+ "version": "7.2.0",
4
4
  "description": "Fast and tiny expression evaluator with common syntax microlanguage.",
5
5
  "main": "subscript.js",
6
6
  "module": "subscript.js",
package/parse.js CHANGED
@@ -50,11 +50,11 @@ id = parse.id = n => skip(isId),
50
50
 
51
51
  // operator/token lookup table
52
52
  // lookup[0] is id parser to let configs redefine it
53
- lookup = []
53
+ lookup = [],
54
54
 
55
55
 
56
56
  // create operator checker/mapper (see examples)
57
- parse.set = (
57
+ token = (
58
58
  op,
59
59
  prec=SPACE,
60
60
  map,
@@ -64,12 +64,11 @@ parse.set = (
64
64
  word=op.toUpperCase()!==op // make sure word boundary comes after word operator
65
65
  ) => lookup[c] = (a, curPrec, from=idx) =>
66
66
  (curPrec<prec && (l<2||cur.substr(idx,l)==op) && (!word||!isId(cur.charCodeAt(idx+l))) && (idx+=l, map(a, curPrec))) ||
67
- (idx=from, prev?.(a, curPrec))
67
+ (idx=from, prev?.(a, curPrec)),
68
68
 
69
69
  // right assoc is indicated by negative precedence (meaning go from right to left)
70
- parse.binary = (op, prec, right) => parse.set(op, prec, (a, b) => a && (b=expr(prec-!!right)) && [op,a,b] )
71
- parse.unary = (op, prec, post) => parse.set(op, prec, a => !a && (a=expr(prec-1)) && [op, a])
72
- parse.nary = (op, prec) => parse.set(op, prec, (a, b) => a && (b=expr(prec)) && (a[0] === op && a[2] ? (a.push(b), a) : [op,a,b]))
73
-
70
+ binary = (op, prec, right) => token(op, prec, (a, b) => a && (b=expr(prec-!!right)) && [op,a,b] ),
71
+ unary = (op, prec, post) => token(op, prec, a => post ? (a && [op, a]) : (!a && (a=expr(prec-1)) && [op, a])),
72
+ nary = (op, prec) => token(op, prec, (a, b) => a && (b=expr(prec)) && (a[0] === op && a[2] ? (a.push(b), a) : [op,a,b]))
74
73
 
75
74
  export default parse
package/subscript.js CHANGED
@@ -1,5 +1,5 @@
1
- import parse, { lookup, skip, cur, idx, err, expr } from './parse.js'
2
- import compile from './compile.js'
1
+ import parse, { lookup, nary, binary, unary, token, skip, err, expr } from './parse.js'
2
+ import compile, { operator } from './compile.js'
3
3
 
4
4
  const OPAREN=40, CPAREN=41, OBRACK=91, CBRACK=93, SPACE=32, DQUOTE=34, PERIOD=46, _0=48, _9=57,
5
5
  PREC_SEQ=1, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
@@ -9,11 +9,22 @@ const subscript = s => (s=parse(s), ctx => (s.call?s:(s=compile(s)))(ctx)),
9
9
 
10
10
  // set any operator
11
11
  // right assoc is indicated by negative precedence (meaning go from right to left)
12
- set = subscript.set = (op, prec, fn) =>
13
- (fn[0]||fn[1]) ? (prec ? parse.set(op,prec,fn[0]) : (lookup[op.charCodeAt(0)||1]=fn[0]), compile.set(op, fn[1])) : (
14
- !fn.length ? (parse.nary(op, prec), compile.nary(op, fn)) :
15
- fn.length > 1 ? (parse.binary(op, Math.abs(prec), prec<0), compile.binary(op, fn)) :
16
- (parse.unary(op, prec), compile.unary(op, fn))
12
+ set = (op, prec, fn) =>
13
+ (fn[0]||fn[1]) ? (prec ? token(op,prec,fn[0]) : (lookup[op.charCodeAt(0)||1]=fn[0]), operator(op, fn[1])) : (
14
+ !fn.length ? (
15
+ nary(op, prec),
16
+ operator(op, (...args) => (args=args.map(compile), ctx => fn(...args.map(arg=>arg(ctx)))))
17
+ ) :
18
+ fn.length > 1 ? (
19
+ binary(op, Math.abs(prec), prec<0),
20
+ operator(op,
21
+ (a,b) => b && (a=compile(a),b=compile(b), !a.length&&!b.length ? (a=fn(a(),b()),()=>a) : ctx => fn(a(ctx),b(ctx)))
22
+ )
23
+ ) :
24
+ (
25
+ unary(op, prec),
26
+ operator(op, (a,b) => !b && (a=compile(a), !a.length ? (a=fn(a()),()=>a) : ctx => fn(a(ctx))))
27
+ )
17
28
  ),
18
29
 
19
30
  num = a => a ? err() : ['', (a=+skip(c => c === PERIOD || (c>=_0 && c<=_9) || (c===69||c===101?2:0)))!=a?err():a],
@@ -27,6 +38,7 @@ inc = (op, prec, fn, ev) => [op, prec, [
27
38
  (ctx => fn(ctx,a)) // ++a
28
39
  )
29
40
  ]],
41
+
30
42
  list = [
31
43
  // literals
32
44
  // null operator returns first value (needed for direct literals)
@@ -111,4 +123,6 @@ list = [
111
123
  for (;list[2];) set(...list.splice(0,3))
112
124
 
113
125
  export default subscript
114
- export {compile, parse}
126
+ export {set}
127
+ export * from './parse.js'
128
+ export * from './compile.js'
package/subscript.min.js CHANGED
@@ -1 +1 @@
1
- let e,t,r=r=>(e=0,t=r,r=s(),t[e]?a():r||""),a=(r="Bad syntax",a=t[e],n=t.slice(0,e).split("\n"),s=n.pop())=>{throw SyntaxError(`${r} \`${a}\` at ${n.length}:${s.length}`)},n=(r=1,a=e,n)=>{if("number"==typeof r)e+=r;else for(;n=r(t.charCodeAt(e));)e+=n;return t.slice(a,e)},s=(t=0,n,s,l,o,y)=>{for(;(s=r.space())&&(o=((y=h[s])&&y(l,t))??(!l&&r.id()));)l=o;return n&&(s==n?e++:a()),l},l=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e;r.space=r=>{for(;(r=t.charCodeAt(e))<=32;)e++;return r},r.id=e=>n(l);let h=[];r.set=(r,a=32,n,s=r.charCodeAt(0),o=r.length,y=h[s],i=r.toUpperCase()!==r)=>h[s]=(s,h,c=e)=>h<a&&(o<2||t.substr(e,o)==r)&&(!i||!l(t.charCodeAt(e+o)))&&(e+=o,n(s,h))||(e=c,y?.(s,h)),r.binary=(e,t,a)=>r.set(e,t,((r,n)=>r&&(n=s(t-!!a))&&[e,r,n])),r.unary=(e,t,a)=>r.set(e,t,(r=>!r&&(r=s(t-1))&&[e,r])),r.nary=(e,t)=>r.set(e,t,((r,a)=>r&&(a=s(t))&&(r[0]===e&&r[2]?(r.push(a),r):[e,r,a])));const o=e=>Array.isArray(e)?y[e[0]](...e.slice(1)):t=>t?.[e],y={};o.set=(e,t,r=y[e])=>y[e]=(...e)=>t(...e)||r&&r(...e),o.binary=(e,t)=>o.set(e,((e,r)=>r&&(e=o(e),r=o(r),e.length||r.length?a=>t(e(a),r(a)):(e=t(e(),r()),()=>e)))),o.unary=(e,t)=>o.set(e,((e,r)=>!r&&((e=o(e)).length?r=>t(e(r)):(e=t(e()),()=>e)))),o.nary=(e,t)=>o.set(e,((...e)=>(e=e.map(o),r=>t(...e.map((e=>e(r)))))));const i=e=>(e=r(e),t=>(e.call?e:e=o(e))(t)),c=i.set=(e,t,a)=>a[0]||a[1]?(t?r.set(e,t,a[0]):h[e.charCodeAt(0)||1]=a[0],o.set(e,a[1])):a.length?a.length>1?(r.binary(e,Math.abs(t),t<0),o.binary(e,a)):(r.unary(e,t),o.unary(e,a)):(r.nary(e,t),o.nary(e,a)),p=e=>e?a():["",(e=+n((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?a():e],u=(e,t,r,a)=>[e,t,[r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,s(t-1)],a=(e,t)=>"("===e[0]?a(e[1]):"."===e[0]?(t=e[2],e=o(e[1]),a=>r(e(a),t)):"["===e[0]?([,e,t]=e,e=o(e),t=o(t),a=>r(e(a),t(a))):t=>r(t,e)]],g=["",,[,e=>()=>e],'"',,[e=>e?a():["",(n()+n((e=>e-34?1:0))+(n()||a("Bad string"))).slice(1,-1)]],".",,[e=>!e&&p()],...Array(10).fill(0).flatMap(((e,t)=>[""+t,0,[p]])),",",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,...u("++",15,((e,t)=>++e[t])),...u("--",15,((e,t)=>--e[t])),"[",18,[e=>e&&["[",e,s(0,93)||a()],(e,t)=>t&&(e=o(e),t=o(t),r=>e(r)[t(r)])],".",18,[(e,t)=>e&&(t=s(18))&&[".",e,t],(e,t)=>(e=o(e),t=t[0]?t:t[1],r=>e(r)[t])],"(",18,[e=>!e&&["(",s(0,41)||a()],o],"(",18,[e=>e&&["(",e,s(0,41)||""],(e,t,r,a)=>null!=t&&(a=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(o),e=>t.map((t=>t(e)))):(t=o(t),e=>[t(e)]),"."===e[0]?(r=e[2],e=o(e[1]),t=>e(t)[r](...a(t))):"["===e[0]?(r=o(e[2]),e=o(e[1]),t=>e(t)[r(t)](...a(t))):(e=o(e),t=>e(t)(...a(t))))]];for(;g[2];)c(...g.splice(0,3));export{o as compile,i as default,r as parse};
1
+ let e,t,r=r=>(e=0,t=r,r=n(),t[e]?l():r||""),l=(r="Bad syntax",l=t[e],a=t.slice(0,e).split("\n"),n=a.pop())=>{throw SyntaxError(`${r} \`${l}\` at ${a.length}:${n.length}`)},a=(r=1,l=e,a)=>{if("number"==typeof r)e+=r;else for(;a=r(t.charCodeAt(e));)e+=a;return t.slice(l,e)},n=(t=0,a,n,s,h,o)=>{for(;(n=r.space())&&(h=((o=p[n])&&o(s,t))??(!s&&r.id()));)s=h;return a&&(n==a?e++:l()),s},s=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},o=r.id=e=>a(s),p=[],c=(r,l=32,a,n=r.charCodeAt(0),h=r.length,o=p[n],c=r.toUpperCase()!==r)=>p[n]=(n,p,i=e)=>p<l&&(h<2||t.substr(e,h)==r)&&(!c||!s(t.charCodeAt(e+h)))&&(e+=h,a(n,p))||(e=i,o?.(n,p)),i=(e,t,r)=>c(e,t,((l,a)=>l&&(a=n(t-!!r))&&[e,l,a])),g=(e,t,r)=>c(e,t,(l=>r?l&&[e,l]:!l&&(l=n(t-1))&&[e,l])),f=(e,t)=>c(e,t,((r,l)=>r&&(l=n(t))&&(r[0]===e&&r[2]?(r.push(l),r):[e,r,l])));const d=e=>Array.isArray(e)?u[e[0]](...e.slice(1)):t=>t?.[e],u={},A=(e,t,r=u[e])=>u[e]=(...e)=>t(...e)||r&&r(...e),y=e=>(e=r(e),t=>(e.call?e:e=d(e))(t)),C=(e,t,r)=>r[0]||r[1]?(t?c(e,t,r[0]):p[e.charCodeAt(0)||1]=r[0],A(e,r[1])):r.length?r.length>1?(i(e,Math.abs(t),t<0),A(e,((e,t)=>t&&(e=d(e),t=d(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=d(e)).length?t=>r(e(t)):(e=r(e()),()=>e))))):(f(e,t),A(e,((...e)=>(e=e.map(d),t=>r(...e.map((e=>e(t)))))))),m=e=>e?l():["",(e=+a((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?l():e],$=(e,t,r,l)=>[e,t,[r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,n(t-1)],l=(e,t)=>"("===e[0]?l(e[1]):"."===e[0]?(t=e[2],e=d(e[1]),l=>r(e(l),t)):"["===e[0]?([,e,t]=e,e=d(e),t=d(t),l=>r(e(l),t(l))):t=>r(t,e)]],b=["",,[,e=>()=>e],'"',,[e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)]],".",,[e=>!e&&m()],...Array(10).fill(0).flatMap(((e,t)=>[""+t,0,[m]])),",",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,...$("++",15,((e,t)=>++e[t])),...$("--",15,((e,t)=>--e[t])),"[",18,[e=>e&&["[",e,n(0,93)||l()],(e,t)=>t&&(e=d(e),t=d(t),r=>e(r)[t(r)])],".",18,[(e,t)=>e&&(t=n(18))&&[".",e,t],(e,t)=>(e=d(e),t=t[0]?t:t[1],r=>e(r)[t])],"(",18,[e=>!e&&["(",n(0,41)||l()],d],"(",18,[e=>e&&["(",e,n(0,41)||""],(e,t,r,l)=>null!=t&&(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(d),e=>t.map((t=>t(e)))):(t=d(t),e=>[t(e)]),"."===e[0]?(r=e[2],e=d(e[1]),t=>e(t)[r](...l(t))):"["===e[0]?(r=d(e[2]),e=d(e[1]),t=>e(t)[r(t)](...l(t))):(e=d(e),t=>e(t)(...l(t))))]];for(;b[2];)C(...b.splice(0,3));export{i as binary,d as compile,t as cur,y as default,l as err,n as expr,o as id,e as idx,s as isId,p as lookup,f as nary,A as operator,u as operators,r as parse,C as set,a as skip,h as space,c as token,g as unary};