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 +2 -2
- package/justin.min.js +1 -1
- package/package.json +1 -1
- package/parse.js +88 -88
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
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
|
-
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
longErr = (msg='Bad syntax',
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
skip = (is=1, from=idx, l) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
// a + b - c
|
|
31
|
-
expr = (prec=0, end, cc, token, newNode, fn) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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
|