subscript 7.5.0 → 7.5.1

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/justin.js CHANGED
@@ -54,8 +54,8 @@ lookup[DQUOTE] = string(DQUOTE)
54
54
  lookup[QUOTE] = string(QUOTE)
55
55
 
56
56
  // /**/, //
57
- token('/*', 20, (a, prec) => (skip(c => c !== 42 && cur.charCodeAt(idx + 1) !== 47), skip(2), a || expr(prec)))
58
- token('//', 20, (a, prec) => (skip(c => c >= 32), a || expr(prec)))
57
+ token('/*', 20, (a, prec) => (skip(c => c !== 42 && cur.charCodeAt(idx + 1) !== 47), skip(2), a || expr(prec) || ['']))
58
+ token('//', 20, (a, prec) => (skip(c => c >= 32), a || expr(prec) || ['']))
59
59
 
60
60
  // literals
61
61
  token('null', 20, a => a ? err() : ['', null])
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)),g=(e,t,r=0)=>c(e,t,((l,n)=>l&&(n=s(t-r/2))&&[e,l,n])),f=(e,t,r)=>c(e,t,(l=>r?l&&[e,l]:!l&&(l=s(t-.5))&&[e,l])),u=(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 d=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=d(e))(t)),$=(e,t,r)=>r.length?r.length>1?(g(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))))):(f(e,t),A(e,((e,t)=>!t&&((e=d(e)).length?t=>r(e(t)):(e=r(e()),()=>e))))):(u(e,Math.abs(t),t<0),A(e,((...e)=>(e=e.map(d),t=>r(...e.map((e=>e(t)))))))),y=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)=>(c(e,t,(r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,s(t-1)])),A(e,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)));A("",(e=>()=>e)),o[34]=e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)],o[46]=e=>!e&&y();for(let e=0;e<9;e++)o[48+e]=y;$(",",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])),c("[",18,(e=>e&&["[",e,s(0,93)||l()])),A("[",((e,t)=>t&&(e=d(e),t=d(t),r=>e(r)[t(r)]))),c(".",18,((e,t)=>e&&(t=s(18))&&[".",e,t])),A(".",((e,t)=>(e=d(e),t=t[0]?t:t[1],r=>e(r)[t]))),c("(",18,(e=>!e&&["(",s(0,41)||l()])),c("(",18,((e,t)=>e&&((t=s(0,41))?["(",e,t]:["(",e,""]))),A("(",((e,t,r,l)=>null==t?d(e):(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))))));let x={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},E=r=>(n,s,i="")=>{for(n&&l("Unexpected string"),a();(s=t.charCodeAt(e))-r;)92===s?(a(),s=a(),i+=x[s]||s):i+=a();return a(),["",i]};$("===",9,((e,t)=>e===t)),$("!==",9,((e,t)=>e!==t)),$("~",15,(e=>~e)),c("?",3,((e,t,r)=>e&&(t=s(2,58))&&["?",e,t,s(3)])),A("?",((e,t,r)=>(e=d(e),t=d(t),r=d(r),l=>e(l)?t(l):r(l)))),$("??",6,((e,t)=>e??t)),c("?.",18,(e=>e&&["?.",e])),A("?.",(e=>(e=d(e),t=>e(t)||(()=>{})))),c("?.",18,((e,t)=>e&&!(t=s(18))?.map&&["?.",e,t])),A("?.",((e,t)=>t&&(e=d(e),r=>e(r)?.[t]))),A("(",((e,t,r,l)=>null!=t&&"?."===e[0]&&(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(d),e=>t.map((t=>t(e)))):(t=d(t),e=>[t(e)]),r=e[2],e=d(e[1]),t=>e(t)?.[r](...l(t))))),$("in",10,((e,t)=>e in t)),o[34]=E(34),o[39]=E(39),c("/*",20,((r,l)=>(a((r=>42!==r&&47!==t.charCodeAt(e+1))),a(2),r||s(l)))),c("//",20,((e,t)=>(a((e=>e>=32)),e||s(t)))),c("null",20,(e=>e?l():["",null])),c("true",20,(e=>e?l():["",!0])),c("false",20,(e=>e?l():["",!1])),c("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)),c("[",20,(e=>!e&&["[",s(0,93)||""])),A("[",((e,t)=>!t&&(e?","===e[0]?(e=e.slice(1).map(d),t=>e.map((e=>e(t)))):(e=d(e),t=>[e(t)]):()=>[]))),c("{",20,(e=>!e&&["{",s(0,125)||""])),A("{",((e,t)=>e?","===e[0]?(e=e.slice(1).map(d),t=>Object.fromEntries(e.map((e=>e(t))))):":"===e[0]?(e=d(e),t=>Object.fromEntries([e(t)])):(t=d(e),r=>({[e]:t(r)})):e=>({}))),c(":",1.1,((e,t)=>[":",e,s(1.1)||l()])),A(":",((e,t)=>(t=d(t),e=Array.isArray(e)?d(e):(e=>e).bind(0,e),r=>[e(r),t(r)])));export{g as binary,d 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,u as nary,A as operator,m as operators,r as parse,$ as set,a as skip,h as space,c as token,f 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)),g=(e,t,r=0)=>c(e,t,((l,n)=>l&&(n=s(t-r/2))&&[e,l,n])),f=(e,t,r)=>c(e,t,(l=>r?l&&[e,l]:!l&&(l=s(t-.5))&&[e,l])),u=(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 d=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=d(e))(t)),$=(e,t,r)=>r.length?r.length>1?(g(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))))):(f(e,t),A(e,((e,t)=>!t&&((e=d(e)).length?t=>r(e(t)):(e=r(e()),()=>e))))):(u(e,Math.abs(t),t<0),A(e,((...e)=>(e=e.map(d),t=>r(...e.map((e=>e(t)))))))),y=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)=>(c(e,t,(r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,s(t-1)])),A(e,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)));A("",(e=>()=>e)),o[34]=e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)],o[46]=e=>!e&&y();for(let e=0;e<9;e++)o[48+e]=y;$(",",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])),c("[",18,(e=>e&&["[",e,s(0,93)||l()])),A("[",((e,t)=>t&&(e=d(e),t=d(t),r=>e(r)[t(r)]))),c(".",18,((e,t)=>e&&(t=s(18))&&[".",e,t])),A(".",((e,t)=>(e=d(e),t=t[0]?t:t[1],r=>e(r)[t]))),c("(",18,(e=>!e&&["(",s(0,41)||l()])),c("(",18,((e,t)=>e&&((t=s(0,41))?["(",e,t]:["(",e,""]))),A("(",((e,t,r,l)=>null==t?d(e):(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))))));let x={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},E=r=>(n,s,i="")=>{for(n&&l("Unexpected string"),a();(s=t.charCodeAt(e))-r;)92===s?(a(),s=a(),i+=x[s]||s):i+=a();return a(),["",i]};$("===",9,((e,t)=>e===t)),$("!==",9,((e,t)=>e!==t)),$("~",15,(e=>~e)),c("?",3,((e,t,r)=>e&&(t=s(2,58))&&["?",e,t,s(3)])),A("?",((e,t,r)=>(e=d(e),t=d(t),r=d(r),l=>e(l)?t(l):r(l)))),$("??",6,((e,t)=>e??t)),c("?.",18,(e=>e&&["?.",e])),A("?.",(e=>(e=d(e),t=>e(t)||(()=>{})))),c("?.",18,((e,t)=>e&&!(t=s(18))?.map&&["?.",e,t])),A("?.",((e,t)=>t&&(e=d(e),r=>e(r)?.[t]))),A("(",((e,t,r,l)=>null!=t&&"?."===e[0]&&(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(d),e=>t.map((t=>t(e)))):(t=d(t),e=>[t(e)]),r=e[2],e=d(e[1]),t=>e(t)?.[r](...l(t))))),$("in",10,((e,t)=>e in t)),o[34]=E(34),o[39]=E(39),c("/*",20,((r,l)=>(a((r=>42!==r&&47!==t.charCodeAt(e+1))),a(2),r||s(l)||[""]))),c("//",20,((e,t)=>(a((e=>e>=32)),e||s(t)||[""]))),c("null",20,(e=>e?l():["",null])),c("true",20,(e=>e?l():["",!0])),c("false",20,(e=>e?l():["",!1])),c("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)),c("[",20,(e=>!e&&["[",s(0,93)||""])),A("[",((e,t)=>!t&&(e?","===e[0]?(e=e.slice(1).map(d),t=>e.map((e=>e(t)))):(e=d(e),t=>[e(t)]):()=>[]))),c("{",20,(e=>!e&&["{",s(0,125)||""])),A("{",((e,t)=>e?","===e[0]?(e=e.slice(1).map(d),t=>Object.fromEntries(e.map((e=>e(t))))):":"===e[0]?(e=d(e),t=>Object.fromEntries([e(t)])):(t=d(e),r=>({[e]:t(r)})):e=>({}))),c(":",1.1,((e,t)=>[":",e,s(1.1)||l()])),A(":",((e,t)=>(t=d(t),e=Array.isArray(e)?d(e):(e=>e).bind(0,e),r=>[e(r),t(r)])));export{g as binary,d 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,u as nary,A as operator,m as operators,r as parse,$ as set,a as skip,h as space,c as token,f as unary};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subscript",
3
- "version": "7.5.0",
3
+ "version": "7.5.1",
4
4
  "description": "Fast and tiny expression evaluator with minimal syntax.",
5
5
  "main": "subscript.js",
6
6
  "module": "subscript.js",
package/parse.js CHANGED
@@ -1,95 +1,95 @@
1
- const SPACE=32
1
+ const SPACE = 32
2
2
 
3
3
  // current string, index and collected ids
4
4
  export let idx, cur,
5
5
 
6
- // no handling tagged literals since easily done on user side with cache, if needed
7
- parse = s => (idx=0, cur=s, s = expr(), cur[idx] ? err() : s || ''),
8
-
9
- err = (msg='Bad syntax', frag=cur[idx], prev=cur.slice(0,idx).split('\n'), last=prev.pop()) => {
10
- throw SyntaxError(`${msg} ${frag ? `\`${frag}\` ` : ''}at ${prev.length}:${last.length}`, prev.length)
11
- },
12
-
13
- longErr = (msg='Bad syntax',
14
- frag=cur[idx],
15
- lines=cur.slice(0,idx).split('\n'),
16
- last=lines.pop()
17
- ) => {
18
- let before = cur.slice(idx-10,idx).split('\n').pop()
19
- let after = cur.slice(idx+1, idx+10).split('\n').shift()
20
- let location = lines.length + ':' + last.length
21
- throw EvalError(`${msg} at ${location} \`${before+frag+after}\`\n${' '.repeat(18 + msg.length + location.length + before.length + 1)}^`)
22
- },
23
-
24
- skip = (is=1, from=idx, l) => {
25
- if (typeof is == 'number') idx += is
26
- else while (l=is(cur.charCodeAt(idx))) idx+=l
27
- return cur.slice(from, idx)
28
- },
29
-
30
- // a + b - c
31
- expr = (prec=0, end, cc, token, newNode, fn) => {
32
- // chunk/token parser
33
- while (
34
- ( cc=parse.space() ) && // till not end
35
- // FIXME: extra work is happening here, when lookup bails out due to lower precedence -
36
- // it makes extra `space` call for parent exprs on the same character to check precedence again
37
- (newNode =
38
- ((fn=lookup[cc]) && fn(token, prec)) ?? // if operator with higher precedence isn't found
39
- (!token && parse.id()) // parse literal or quit. token seqs are forbidden: `a b`, `a "b"`, `1.32 a`
6
+ // no handling tagged literals since easily done on user side with cache, if needed
7
+ parse = s => (idx = 0, cur = s, s = expr(), cur[idx] ? err() : s || ''),
8
+
9
+ err = (msg = 'Bad syntax', frag = cur[idx], prev = cur.slice(0, idx).split('\n'), last = prev.pop()) => {
10
+ throw SyntaxError(`${msg} ${frag ? `\`${frag}\` ` : ''}at ${prev.length}:${last.length}`, prev.length)
11
+ },
12
+
13
+ longErr = (msg = 'Bad syntax',
14
+ frag = cur[idx],
15
+ lines = cur.slice(0, idx).split('\n'),
16
+ last = lines.pop()
17
+ ) => {
18
+ let before = cur.slice(idx - 10, idx).split('\n').pop()
19
+ let after = cur.slice(idx + 1, idx + 10).split('\n').shift()
20
+ let location = lines.length + ':' + last.length
21
+ throw EvalError(`${msg} at ${location} \`${before + frag + after}\`\n${' '.repeat(18 + msg.length + location.length + before.length + 1)}^`)
22
+ },
23
+
24
+ skip = (is = 1, from = idx, l) => {
25
+ if (typeof is == 'number') idx += is
26
+ else while (l = is(cur.charCodeAt(idx))) idx += l
27
+ return cur.slice(from, idx)
28
+ },
29
+
30
+ // a + b - c
31
+ expr = (prec = 0, end, cc, token, newNode, fn) => {
32
+ // chunk/token parser
33
+ while (
34
+ (cc = parse.space()) && // till not end
35
+ // FIXME: extra work is happening here, when lookup bails out due to lower precedence -
36
+ // it makes extra `space` call for parent exprs on the same character to check precedence again
37
+ (newNode =
38
+ ((fn = lookup[cc]) && fn(token, prec)) ?? // if operator with higher precedence isn't found
39
+ (!token && parse.id()) // parse literal or quit. token seqs are forbidden: `a b`, `a "b"`, `1.32 a`
40
+ )
41
+ ) token = newNode;
42
+
43
+ // check end character
44
+ // FIXME: can't show "Unclosed paren", because can be unknown operator within group as well
45
+ if (end) cc == end ? idx++ : err()
46
+
47
+ return token
48
+ },
49
+
50
+ isId = c =>
51
+ (c >= 48 && c <= 57) || // 0..9
52
+ (c >= 65 && c <= 90) || // A...Z
53
+ (c >= 97 && c <= 122) || // a...z
54
+ c == 36 || c == 95 || // $, _,
55
+ (c >= 192 && c != 215 && c != 247), // any non-ASCII
56
+
57
+ // skip space chars, return first non-space character
58
+ space = parse.space = cc => { while ((cc = cur.charCodeAt(idx)) <= SPACE) idx++; return cc },
59
+
60
+ id = parse.id = n => skip(isId),
61
+
62
+ // operator/token lookup table
63
+ // lookup[0] is id parser to let configs redefine it
64
+ lookup = [],
65
+
66
+
67
+ // create operator checker/mapper (see examples)
68
+ token = (
69
+ op,
70
+ prec = SPACE,
71
+ map,
72
+ c = op.charCodeAt(0),
73
+ l = op.length,
74
+ prev = lookup[c],
75
+ word = op.toUpperCase() !== op // make sure word boundary comes after word operator
76
+ ) => lookup[c] = (a, curPrec, from = idx) =>
77
+ (curPrec < prec && (l < 2 || cur.substr(idx, l) == op) && (!word || !isId(cur.charCodeAt(idx + l))) && (idx += l, map(a, curPrec))) ||
78
+ (idx = from, prev?.(a, curPrec)),
79
+
80
+ // right assoc is indicated by negative precedence (meaning go from right to left)
81
+ binary = (op, prec, right = 0) => token(op, prec, (a, b) => a && (b = expr(prec - right / 2)) && [op, a, b]),
82
+ unary = (op, prec, post) => token(op, prec, a => post ? (a && [op, a]) : (!a && (a = expr(prec - .5)) && [op, 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
+ ))
40
92
  )
41
- ) token = newNode;
42
-
43
- // check end character
44
- // FIXME: can't show "Unclose paren", because can be unknown operator within group as well
45
- if (end) cc==end?idx++:err()
46
-
47
- return token
48
- },
49
-
50
- isId = c =>
51
- (c >= 48 && c <= 57) || // 0..9
52
- (c >= 65 && c <= 90) || // A...Z
53
- (c >= 97 && c <= 122) || // a...z
54
- c == 36 || c == 95 || // $, _,
55
- (c >= 192 && c != 215 && c != 247), // any non-ASCII
56
-
57
- // skip space chars, return first non-space character
58
- space = parse.space = cc => { while ((cc = cur.charCodeAt(idx)) <= SPACE) idx++; return cc },
59
-
60
- id = parse.id = n => skip(isId),
61
-
62
- // operator/token lookup table
63
- // lookup[0] is id parser to let configs redefine it
64
- lookup = [],
65
-
66
-
67
- // create operator checker/mapper (see examples)
68
- token = (
69
- op,
70
- prec=SPACE,
71
- map,
72
- c=op.charCodeAt(0),
73
- l=op.length,
74
- prev=lookup[c],
75
- word=op.toUpperCase()!==op // make sure word boundary comes after word operator
76
- ) => lookup[c] = (a, curPrec, from=idx) =>
77
- (curPrec<prec && (l<2||cur.substr(idx,l)==op) && (!word||!isId(cur.charCodeAt(idx+l))) && (idx+=l, map(a, curPrec))) ||
78
- (idx=from, prev?.(a, curPrec)),
79
-
80
- // right assoc is indicated by negative precedence (meaning go from right to left)
81
- binary = (op, prec, right=0) => token(op, prec, (a, b) => a && (b=expr(prec-right/2)) && [op,a,b] ),
82
- unary = (op, prec, post) => token(op, prec, a => post ? (a && [op, a]) : (!a && (a=expr(prec-.5)) && [op, 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
- }
93
+ }
94
94
 
95
95
  export default parse