apg-lite
Version:
lightweight JavaScript APG parser
1 lines • 17.6 kB
JavaScript
const Parser=function(){const e=identifiers,t=utilities,s=this,n="parser.js: Parser(): ";s.ast=void 0,s.stats=void 0,s.trace=void 0,s.callbacks=[];let r,a,i,o,h,c,l,d=0,p=0,T=0,g=0,m=0,u=new function(){this.state=e.ACTIVE,this.phraseLength=0,this.refresh=()=>{this.state=e.ACTIVE,this.phraseLength=0}};s.parse=(f,A,E,M)=>{const w=`${n}parse(): `;d=0,p=0,T=0,g=0,m=0,r=void 0,a=void 0,i=void 0,o=void 0,u.refresh(),h=void 0,c=void 0,l=void 0,o=t.stringToChars(E),r=f.rules,a=f.udts;const L=A.toLowerCase();let $;for(const e in r)if(r.hasOwnProperty(e)&&L===r[e].lower){$=r[e].index;break}if(void 0===$)throw new Error(`${w}start rule name '${startRule}' not recognized`);(()=>{const e=`${n}initializeCallbacks(): `;let t,i;for(h=[],c=[],t=0;t<r.length;t+=1)h[t]=void 0;for(t=0;t<a.length;t+=1)c[t]=void 0;const o=[];for(t=0;t<r.length;t+=1)o.push(r[t].lower);for(t=0;t<a.length;t+=1)o.push(a[t].lower);for(const n in s.callbacks)if(s.callbacks.hasOwnProperty(n)){if(t=o.indexOf(n.toLowerCase()),t<0)throw new Error(`${e}syntax callback '${n}' not a rule or udt name`);if(i=s.callbacks[n]?s.callbacks[n]:void 0,"function"!=typeof i&&void 0!==i)throw new Error(`${e}syntax callback[${n}] must be function reference or falsy)`);t<r.length?h[t]=i:c[t-r.length]=i}})(),s.trace&&s.trace.init(r,a,o),s.stats&&s.stats.init(r,a),s.ast&&s.ast.init(r,a,o),l=M,i=[{type:e.RNM,index:$}],x(0,0),i=void 0;let b=!1;switch(u.state){case e.ACTIVE:throw new Error(`${w}final state should never be 'ACTIVE'`);case e.NOMATCH:b=!1;break;case e.EMPTY:case e.MATCH:b=u.phraseLength===o.length;break;default:throw new Error("unrecognized state")}return{success:b,state:u.state,stateName:e.idName(u.state),length:o.length,matched:u.phraseLength,maxMatched:m,maxTreeDepth:T,nodeHits:g}};const f=(t,s,r,a)=>{if(s.phraseLength>r){let e=`${n}opRNM(${t.name}): callback function error: `;throw e+=`sysData.phraseLength: ${s.phraseLength}`,e+=` must be <= remaining chars: ${r}`,new Error(e)}switch(s.state){case e.ACTIVE:if(!a)throw new Error(`${n}opRNM(${t.name}): callback function return error. ACTIVE state not allowed.`);break;case e.EMPTY:s.phraseLength=0;break;case e.MATCH:0===s.phraseLength&&(s.state=e.EMPTY);break;case e.NOMATCH:s.phraseLength=0;break;default:throw new Error(`${n}opRNM(${t.name}): callback function return error. Unrecognized return state: ${s.state}`)}},A=(t,h)=>{let p,T,g;const m=i[t],f=a[m.index];u.UdtIndex=f.index,d||(g=s.ast&&s.ast.udtDefined(m.index),g&&(T=r.length+m.index,p=s.ast.getLength(),s.ast.down(T,f.name)));const A=o.length-h;c[m.index](u,o,h,l),((t,s,r)=>{if(s.phraseLength>r){let e=`${n}opUDT(${t.name}): callback function error: `;throw e+=`sysData.phraseLength: ${s.phraseLength}`,e+=` must be <= remaining chars: ${r}`,new Error(e)}switch(s.state){case e.ACTIVE:throw new Error(`${n}opUDT(${t.name}) ACTIVE state return not allowed.`);case e.EMPTY:if(!t.empty)throw new Error(`${n}opUDT(${t.name}) may not return EMPTY.`);s.phraseLength=0;break;case e.MATCH:if(0===s.phraseLength){if(!t.empty)throw new Error(`${n}opUDT(${t.name}) may not return EMPTY.`);s.state=e.EMPTY}break;case e.NOMATCH:s.phraseLength=0;break;default:throw new Error(`${n}opUDT(${t.name}): callback function return error. Unrecognized return state: ${s.state}`)}})(f,u,A),d||g&&(u.state===e.NOMATCH?s.ast.setLength(p):s.ast.up(T,f.name,h,u.phraseLength))},x=(t,a)=>{const c=`${n}opExecute(): `,E=i[t];switch(g+=1,p>T&&(T=p),p+=1,u.refresh(),s.trace&&s.trace.down(E,a),E.type){case e.ALT:((t,s)=>{const n=i[t];for(let t=0;t<n.children.length&&(x(n.children[t],s),u.state===e.NOMATCH);t+=1);})(t,a);break;case e.CAT:((t,n)=>{let r,a,o,h;const c=i[t];s.ast&&(a=s.ast.getLength()),r=!0,o=n,h=0;for(let t=0;t<c.children.length;t+=1){if(x(c.children[t],o),u.state===e.NOMATCH){r=!1;break}o+=u.phraseLength,h+=u.phraseLength}r?(u.state=0===h?e.EMPTY:e.MATCH,u.phraseLength=h):(u.state=e.NOMATCH,u.phraseLength=0,s.ast&&s.ast.setLength(a))})(t,a);break;case e.REP:((t,n)=>{let r,a,h,c;const l=i[t];if(0===l.max)return u.state=e.EMPTY,void(u.phraseLength=0);for(a=n,h=0,c=0,s.ast&&(r=s.ast.getLength());!(a>=o.length)&&(x(t+1,a),u.state!==e.NOMATCH)&&u.state!==e.EMPTY&&(c+=1,h+=u.phraseLength,a+=u.phraseLength,c!==l.max););u.state===e.EMPTY||c>=l.min?(u.state=0===h?e.EMPTY:e.MATCH,u.phraseLength=h):(u.state=e.NOMATCH,u.phraseLength=0,s.ast&&s.ast.setLength(r))})(t,a);break;case e.RNM:((t,n)=>{let a,c,p;const T=i[t],g=r[T.index],m=h[g.index];if(d||(c=s.ast&&s.ast.ruleDefined(T.index),c&&(a=s.ast.getLength(),s.ast.down(T.index,r[T.index].name))),m){const t=o.length-n;m(u,o,n,l),f(g,u,t,!0),u.state===e.ACTIVE&&(p=i,i=g.opcodes,x(0,n),i=p,m(u,o,n,l),f(g,u,t,!1))}else p=i,i=g.opcodes,x(0,n,u),i=p;d||c&&(u.state===e.NOMATCH?s.ast.setLength(a):s.ast.up(T.index,g.name,n,u.phraseLength))})(t,a);break;case e.TRG:((t,s)=>{const n=i[t];u.state=e.NOMATCH,s<o.length&&n.min<=o[s]&&o[s]<=n.max&&(u.state=e.MATCH,u.phraseLength=1)})(t,a);break;case e.TBS:((t,s)=>{const n=i[t],r=n.string.length;if(u.state=e.NOMATCH,s+r<=o.length){for(let e=0;e<r;e+=1)if(o[s+e]!==n.string[e])return;u.state=e.MATCH,u.phraseLength=r}})(t,a);break;case e.TLS:((t,s)=>{let n;const r=i[t];u.state=e.NOMATCH;const a=r.string.length;if(0!==a){if(s+a<=o.length){for(let e=0;e<a;e+=1)if(n=o[s+e],n>=65&&n<=90&&(n+=32),n!==r.string[e])return;u.state=e.MATCH,u.phraseLength=a}}else u.state=e.EMPTY})(t,a);break;case e.UDT:A(t,a);break;case e.AND:((t,s)=>{switch(d+=1,x(t+1,s),d-=1,u.phraseLength=0,u.state){case e.EMPTY:case e.MATCH:u.state=e.EMPTY;break;case e.NOMATCH:u.state=e.NOMATCH;break;default:throw new Error(`opAND: invalid state ${u.state}`)}})(t,a);break;case e.NOT:((t,s)=>{switch(d+=1,x(t+1,s),d-=1,u.phraseLength=0,u.state){case e.EMPTY:case e.MATCH:u.state=e.NOMATCH;break;case e.NOMATCH:u.state=e.EMPTY;break;default:throw new Error(`opNOT: invalid state ${u.state}`)}})(t,a);break;default:throw new Error(`${c}unrecognized operator`)}d||a+u.phraseLength>m&&(m=a+u.phraseLength),s.stats&&s.stats.collect(E,u),s.trace&&s.trace.up(E,u.state,a,u.phraseLength),p-=1}},Ast=function(){const e=identifiers,t=utilities,s=this;let n,r,a,i=0;const o=[],h=[],c=[];function l(e){let t="";for(;e-- >0;)t+=" ";return t}s.callbacks=[],s.init=(e,t,l)=>{let d;h.length=0,c.length=0,i=0,n=e,r=t,a=l;const p=[];for(d=0;d<n.length;d+=1)p.push(n[d].lower);for(d=0;d<r.length;d+=1)p.push(r[d].lower);for(i=n.length+r.length,d=0;d<i;d+=1)o[d]=void 0;for(const e in s.callbacks)if(s.callbacks.hasOwnProperty(e)){const t=e.toLowerCase();if(d=p.indexOf(t),d<0)throw new Error(`parser.js: Ast()): init: node '${e}' not a rule or udt name`);o[d]=s.callbacks[e]}},s.ruleDefined=e=>!!o[e],s.udtDefined=e=>!!o[n.length+e],s.down=(t,s)=>{const n=c.length;return h.push(n),c.push({name:s,thisIndex:n,thatIndex:void 0,state:e.SEM_PRE,callbackIndex:t,phraseIndex:void 0,phraseLength:void 0,stack:h.length}),n},s.up=(t,s,n,r)=>{const a=c.length,i=h.pop();return c.push({name:s,thisIndex:a,thatIndex:i,state:e.SEM_POST,callbackIndex:t,phraseIndex:n,phraseLength:r,stack:h.length}),c[i].thatIndex=a,c[i].phraseIndex=n,c[i].phraseLength=r,a},s.translate=t=>{let s,n;for(let r=0;r<c.length;r+=1)n=c[r],s=o[n.callbackIndex],s&&(n.state===e.SEM_PRE?s(e.SEM_PRE,a,n.phraseIndex,n.phraseLength,t):s&&s(e.SEM_POST,a,n.phraseIndex,n.phraseLength,t))},s.setLength=e=>{c.length=e,h.length=e>0?c[e-1].stack:0},s.getLength=()=>c.length,s.toXml=()=>{let s="",n=0;return s+='<?xml version="1.0" encoding="utf-8"?>\n',s+=`<root nodes="${c.length/2}" characters="${a.length}">\n`,s+="\x3c!-- input string --\x3e\n",s+=l(n+2),s+=t.charsToString(a),s+="\n",c.forEach((r=>{r.state===e.SEM_PRE?(n+=1,s+=l(n),s+=`<node name="${r.name}" index="${r.phraseIndex}" length="${r.phraseLength}">\n`,s+=l(n+2),s+=t.charsToString(a,r.phraseIndex,r.phraseLength),s+="\n"):(s+=l(n),s+=`</node>\x3c!-- name="${r.name}" --\x3e\n`,n-=1)})),s+="</root>\n",s}},Trace=function(){const e=identifiers,t=utilities,s="parser.js: Trace(): ";let n,r,a,i="",o=0;const h=this,c=e=>{let t="",s=0;if(e>=0)for(;e--;)s+=1,5===s?(t+="|",s=0):t+=".";return t};h.init=(e,t,s)=>{r=e,a=t,n=s};const l=n=>{let i;switch(n.type){case e.ALT:i="ALT";break;case e.CAT:i="CAT";break;case e.REP:i=n.max===1/0?`REP(${n.min},inf)`:`REP(${n.min},${n.max})`;break;case e.RNM:i=`RNM(${r[n.index].name})`;break;case e.TRG:i=`TRG(${n.min},${n.max})`;break;case e.TBS:i=n.string.length>6?`TBS(${t.charsToString(n.string,0,3)}...)`:`TBS(${t.charsToString(n.string,0,6)})`;break;case e.TLS:i=n.string.length>6?`TLS(${t.charsToString(n.string,0,3)}...)`:`TLS(${t.charsToString(n.string,0,6)})`;break;case e.UDT:i=`UDT(${a[n.index].name})`;break;case e.AND:i="AND";break;case e.NOT:i="NOT";break;default:throw new Error(`${s}Trace: opName: unrecognized opcode`)}return i};h.down=(e,s)=>{const r=c(o),a=Math.min(100,n.length-s);let h=t.charsToString(n,s,a);a<n.length-s&&(h+="..."),h=`${r}|-|[${l(e)}]${h}\n`,i+=h,o+=1},h.up=(r,a,h,d)=>{const p=`${s}trace.up: `;o-=1;const T=c(o);let g,m,u;switch(a){case e.EMPTY:u="|E|",m="''";break;case e.MATCH:u="|M|",g=Math.min(100,d),m=g<d?`'${t.charsToString(n,h,g)}...'`:`'${t.charsToString(n,h,g)}'`;break;case e.NOMATCH:u="|N|",m="";break;default:throw new Error(`${p} unrecognized state`)}m=`${T}${u}[${l(r)}]${m}\n`,i+=m},h.displayTrace=()=>i},Stats=function(){const e=identifiers;let t,s,n;const r=[],a=[],i=[];this.init=(e,n)=>{t=e,s=n,p()},this.collect=(t,s)=>{T(n,s.state,s.phraseLength),T(r[t.type],s.state,s.phraseLength),t.type===e.RNM&&T(a[t.index],s.state,s.phraseLength),t.type===e.UDT&&T(i[t.index],s.state,s.phraseLength)},this.displayStats=()=>{let t="";const s={match:0,empty:0,nomatch:0,total:0},n=(e,t,n,r,a)=>{s.match+=t,s.empty+=n,s.nomatch+=r,s.total+=a;return`${e} | ${o(t)} | ${o(n)} | ${o(r)} | ${o(a)} |\n`};return t+=" OPERATOR STATS\n",t+=" | MATCH | EMPTY | NOMATCH | TOTAL |\n",t+=n(" ALT",r[e.ALT].match,r[e.ALT].empty,r[e.ALT].nomatch,r[e.ALT].total),t+=n(" CAT",r[e.CAT].match,r[e.CAT].empty,r[e.CAT].nomatch,r[e.CAT].total),t+=n(" REP",r[e.REP].match,r[e.REP].empty,r[e.REP].nomatch,r[e.REP].total),t+=n(" RNM",r[e.RNM].match,r[e.RNM].empty,r[e.RNM].nomatch,r[e.RNM].total),t+=n(" TRG",r[e.TRG].match,r[e.TRG].empty,r[e.TRG].nomatch,r[e.TRG].total),t+=n(" TBS",r[e.TBS].match,r[e.TBS].empty,r[e.TBS].nomatch,r[e.TBS].total),t+=n(" TLS",r[e.TLS].match,r[e.TLS].empty,r[e.TLS].nomatch,r[e.TLS].total),t+=n(" UDT",r[e.UDT].match,r[e.UDT].empty,r[e.UDT].nomatch,r[e.UDT].total),t+=n(" AND",r[e.AND].match,r[e.AND].empty,r[e.AND].nomatch,r[e.AND].total),t+=n(" NOT",r[e.NOT].match,r[e.NOT].empty,r[e.NOT].nomatch,r[e.NOT].total),t+=n("TOTAL",s.match,s.empty,s.nomatch,s.total),t},this.displayHits=e=>{let t="";const s=(e,t,s,r,a)=>{n.match+=e,n.empty+=t,n.nomatch+=s,n.total+=r;return`| ${o(e)} | ${o(t)} | ${o(s)} | ${o(r)} | ${a}\n`};"string"==typeof e&&"a"===e.toLowerCase()[0]?(a.sort(h),i.sort(h),t+=" RULES/UDTS ALPHABETICALLY\n"):"string"==typeof e&&"i"===e.toLowerCase()[0]?(a.sort(l),i.sort(l),t+=" RULES/UDTS BY INDEX\n"):(a.sort(c),i.sort(c),t+=" RULES/UDTS BY HIT COUNT\n"),t+="| MATCH | EMPTY | NOMATCH | TOTAL | NAME\n";for(let e=0;e<a.length;e+=1){let n=a[e];n.total&&(t+=s(n.match,n.empty,n.nomatch,n.total,n.name))}for(let e=0;e<i.length;e+=1){let n=i[e];n.total&&(t+=s(n.match,n.empty,n.nomatch,n.total,n.name))}return t};const o=e=>e<10?` ${e}`:e<100?` ${e}`:e<1e3?` ${e}`:e<1e4?` ${e}`:e<1e5?` ${e}`:e<1e6?` ${e}`:`${e}`,h=(e,t)=>e.lower<t.lower?-1:e.lower>t.lower?1:0,c=(e,t)=>e.total<t.total?1:e.total>t.total?-1:h(e,t),l=(e,t)=>e.index<t.index?-1:e.index>t.index?1:0,d=function(){this.empty=0,this.match=0,this.nomatch=0,this.total=0},p=()=>{r.length=0,n=new d,r[e.ALT]=new d,r[e.CAT]=new d,r[e.REP]=new d,r[e.RNM]=new d,r[e.TRG]=new d,r[e.TBS]=new d,r[e.TLS]=new d,r[e.UDT]=new d,r[e.AND]=new d,r[e.NOT]=new d,a.length=0;for(let e=0;e<t.length;e+=1)a.push({empty:0,match:0,nomatch:0,total:0,name:t[e].name,lower:t[e].lower,index:t[e].index});if(s.length>0){i.length=0;for(let e=0;e<s.length;e+=1)i.push({empty:0,match:0,nomatch:0,total:0,name:s[e].name,lower:s[e].lower,index:s[e].index})}},T=(t,s)=>{switch(t.total+=1,s){case e.EMPTY:t.empty+=1;break;case e.MATCH:t.match+=1;break;case e.NOMATCH:t.nomatch+=1;break;default:throw new Error(`parser.js: Stats(): collect(): incStat(): unrecognized state: ${s}`)}}},utilities={stringToChars:e=>[...e].map((e=>e.codePointAt(0))),charsToString:(e,t,s)=>{let n=e;for(;!(void 0===t||t<0);){if(void 0===s){n=e.slice(t);break}if(s<=0)return"";n=e.slice(t,t+s);break}return String.fromCodePoint(...n)}},identifiers={ALT:1,CAT:2,REP:3,RNM:4,TRG:5,TBS:6,TLS:7,UDT:11,AND:12,NOT:13,ACTIVE:100,MATCH:101,EMPTY:102,NOMATCH:103,SEM_PRE:200,SEM_POST:201,SEM_OK:300,idName:e=>{switch(e){case identifiers.ALT:return"ALT";case identifiers.CAT:return"CAT";case identifiers.REP:return"REP";case identifiers.RNM:return"RNM";case identifiers.TRG:return"TRG";case identifiers.TBS:return"TBS";case identifiers.TLS:return"TLS";case identifiers.UDT:return"UDT";case identifiers.AND:return"AND";case identifiers.NOT:return"NOT";case identifiers.ACTIVE:return"ACTIVE";case identifiers.EMPTY:return"EMPTY";case identifiers.MATCH:return"MATCH";case identifiers.NOMATCH:return"NOMATCH";case identifiers.SEM_PRE:return"SEM_PRE";case identifiers.SEM_POST:return"SEM_POST";case identifiers.SEM_OK:return"SEM_OK";default:return"UNRECOGNIZED STATE"}}},Grammar=function(){this.grammarObject="grammarObject",this.rules=[],this.rules[0]={name:"float",lower:"float",index:0,isBkr:!1},this.rules[1]={name:"sign",lower:"sign",index:1,isBkr:!1},this.rules[2]={name:"decimal",lower:"decimal",index:2,isBkr:!1},this.rules[3]={name:"integer",lower:"integer",index:3,isBkr:!1},this.rules[4]={name:"dot",lower:"dot",index:4,isBkr:!1},this.rules[5]={name:"fraction",lower:"fraction",index:5,isBkr:!1},this.rules[6]={name:"exponent",lower:"exponent",index:6,isBkr:!1},this.rules[7]={name:"esign",lower:"esign",index:7,isBkr:!1},this.rules[8]={name:"exp",lower:"exp",index:8,isBkr:!1},this.udts=[],this.rules[0].opcodes=[],this.rules[0].opcodes[0]={type:2,children:[1,3,4]},this.rules[0].opcodes[1]={type:3,min:0,max:1},this.rules[0].opcodes[2]={type:4,index:1},this.rules[0].opcodes[3]={type:4,index:2},this.rules[0].opcodes[4]={type:3,min:0,max:1},this.rules[0].opcodes[5]={type:4,index:6},this.rules[1].opcodes=[],this.rules[1].opcodes[0]={type:1,children:[1,2]},this.rules[1].opcodes[1]={type:7,string:[43]},this.rules[1].opcodes[2]={type:7,string:[45]},this.rules[2].opcodes=[],this.rules[2].opcodes[0]={type:1,children:[1,8]},this.rules[2].opcodes[1]={type:2,children:[2,3]},this.rules[2].opcodes[2]={type:4,index:3},this.rules[2].opcodes[3]={type:3,min:0,max:1},this.rules[2].opcodes[4]={type:2,children:[5,6]},this.rules[2].opcodes[5]={type:4,index:4},this.rules[2].opcodes[6]={type:3,min:0,max:1},this.rules[2].opcodes[7]={type:4,index:5},this.rules[2].opcodes[8]={type:2,children:[9,10]},this.rules[2].opcodes[9]={type:4,index:4},this.rules[2].opcodes[10]={type:4,index:5},this.rules[3].opcodes=[],this.rules[3].opcodes[0]={type:3,min:1,max:1/0},this.rules[3].opcodes[1]={type:5,min:48,max:57},this.rules[4].opcodes=[],this.rules[4].opcodes[0]={type:7,string:[46]},this.rules[5].opcodes=[],this.rules[5].opcodes[0]={type:3,min:1,max:1/0},this.rules[5].opcodes[1]={type:5,min:48,max:57},this.rules[6].opcodes=[],this.rules[6].opcodes[0]={type:2,children:[1,2,4]},this.rules[6].opcodes[1]={type:7,string:[101]},this.rules[6].opcodes[2]={type:3,min:0,max:1},this.rules[6].opcodes[3]={type:4,index:7},this.rules[6].opcodes[4]={type:4,index:8},this.rules[7].opcodes=[],this.rules[7].opcodes[0]={type:1,children:[1,2]},this.rules[7].opcodes[1]={type:7,string:[43]},this.rules[7].opcodes[2]={type:7,string:[45]},this.rules[8].opcodes=[],this.rules[8].opcodes[0]={type:3,min:1,max:1/0},this.rules[8].opcodes[1]={type:5,min:48,max:57},this.toString=function(){let e="";return e+=";\n",e+="; floating point number\n",e+=";\n",e+="float = [sign] decimal [exponent]\n",e+='sign = "+" / "-"\n',e+="decimal = integer [dot [fraction]]\n",e+=" / dot fraction\n",e+="integer = 1*%d48-57\n",e+='dot = "."\n',e+="fraction = 1*%d48-57\n",e+='exponent = "e" [esign] exp\n',e+='esign = "+" / "-"\n',e+="exp = 1*%d48-57\n",';\n; floating point number\n;\nfloat = [sign] decimal [exponent]\nsign = "+" / "-"\ndecimal = integer [dot [fraction]]\n / dot fraction\ninteger = 1*%d48-57\ndot = "."\nfraction = 1*%d48-57\nexponent = "e" [esign] exp\nesign = "+" / "-"\nexp = 1*%d48-57\n'}},parser=new Parser,grammar=new Grammar,id=identifiers,utils=utilities;$("#grammar-bnf").html(grammar.toString()),parser.callbacks.float=(e,t,s,n)=>{switch(e.state){case id.ACTIVE:n.float="",n.sign="",n.decimal="",n.exponent="";break;case id.MATCH:n.float=utils.charsToString(t,s,e.phraseLength)}},parser.callbacks.sign=(e,t,s,n)=>{e.state===id.MATCH&&(n.sign=utils.charsToString(t,s,e.phraseLength))},parser.callbacks.decimal=(e,t,s,n)=>{e.state===id.MATCH&&(n.decimal=utils.charsToString(t,s,e.phraseLength))},parser.callbacks.exponent=(e,t,s,n)=>{e.state===id.MATCH&&(n.exponent=utils.charsToString(t,s,e.phraseLength))};const data={},parseNumber=()=>{const e=$("#string").val(),t=parser.parse(grammar,"float",e,data);$("#result").html("Parser Result<br>"+JSON.stringify(t));let s="";t.success?(s+="Parsed Floating Point Number Parts\n",s+=` sign: ${data.sign}\n`,s+=` decimal: ${data.decimal}\n`,s+=`exponent: ${data.exponent}\n`):s+="Invalid Floating Point Number\n",$("#values").html(s)};$(document).ready((()=>{$("#parse").click(parseNumber),$("#string").val("+1.23E-10")}));