parser-combinators 1.2.0 → 1.2.2
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/dist/index.min.js +4 -0
- package/dist/index.min.mjs +4 -0
- package/dist-esm/index.d.ts +3 -0
- package/dist-esm/index.js +3 -0
- package/dist-esm/parser.d.ts +9 -0
- package/dist-esm/parser.js +18 -0
- package/dist-esm/parsers/any.d.ts +16 -0
- package/dist-esm/parsers/any.js +44 -0
- package/dist-esm/parsers/anyString.d.ts +15 -0
- package/dist-esm/parsers/anyString.js +82 -0
- package/dist-esm/parsers/between.d.ts +5 -0
- package/dist-esm/parsers/between.js +17 -0
- package/dist-esm/parsers/exhaust.d.ts +5 -0
- package/dist-esm/parsers/exhaust.js +22 -0
- package/dist-esm/parsers/index.d.ts +12 -0
- package/dist-esm/parsers/index.js +12 -0
- package/dist-esm/parsers/many.d.ts +17 -0
- package/dist-esm/parsers/many.js +55 -0
- package/dist-esm/parsers/map.d.ts +5 -0
- package/dist-esm/parsers/map.js +18 -0
- package/dist-esm/parsers/opt.d.ts +5 -0
- package/dist-esm/parsers/opt.js +13 -0
- package/dist-esm/parsers/recovery.d.ts +14 -0
- package/dist-esm/parsers/recovery.js +49 -0
- package/dist-esm/parsers/regex.d.ts +5 -0
- package/dist-esm/parsers/regex.js +17 -0
- package/dist-esm/parsers/seq.d.ts +16 -0
- package/dist-esm/parsers/seq.js +14 -0
- package/dist-esm/parsers/str.d.ts +17 -0
- package/dist-esm/parsers/str.js +32 -0
- package/dist-esm/parsers/utilities.d.ts +33 -0
- package/dist-esm/parsers/utilities.js +85 -0
- package/dist-esm/parsers/values.d.ts +31 -0
- package/dist-esm/parsers/values.js +44 -0
- package/dist-esm/types.d.ts +40 -0
- package/dist-esm/types.js +38 -0
- package/package.json +9 -5
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var a=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var l=a(p=>{"use strict";Object.defineProperty(p,"__esModule",{value:!0});p.ParseError=void 0;p.isFailure=be;p.success=k;p.failure=ee;p.result=ve;p.fail=Pe;function be(e){return!e.success}function k(e,n){return{success:!0,value:n,ctx:e}}function ee(e,n,t){return{success:!1,expected:n,ctx:e,history:t}}function ve(e){return n=>k(n,e)}function Pe(e){return n=>ee(n,e,[e])}var B=class extends Error{constructor(n,t,r,s){super(n),this.index=r,this.history=s,[this.line,this.column,this.row]=this.getInputData(t,r)}getInputData(n,t){let r=n.split(`
|
|
2
|
+
`),s=0;for(;t>0;){if(r[s].length>t)return[r[s],t+1,s+1];t-=r[s].length+1,s+=1}return[r[s],t+1,s+1]}getPrettyErrorMessage(){return`${this.message} (line ${this.row}, col ${this.column}):
|
|
3
|
+
${this.line}
|
|
4
|
+
${(this.column>0?"-".repeat(this.column-1):"")+"^"}`}};p.ParseError=B});var te=a(z=>{"use strict";Object.defineProperty(z,"__esModule",{value:!0});z.anyString=Oe;var re=l();function Oe(e){let n=`'${e[e.length-1][0]}'`,t;return Object.assign(r=>{t??=we(e);let s=Me(t,r.text,r.index);return s?(0,re.success)({...r,index:s.end},e[s.matchIndex][0]):(0,re.failure)(r,n,["any",n])},{parserType:"anyString",matches:e})}function we(e){let n=new Map;return e.forEach((t,r)=>w(n,t,r)),n}function w(e,n,t,r=0){if(r>=n[0].length)e.matchIndex!=null?e.matchIndex=Math.min(e.matchIndex,t):e.matchIndex=t;else{let s=n[0][r],u=s.toLowerCase(),i=s.toUpperCase(),g=new Map;if(n[1]&&u!==i){let q=e.get(u)??g,_=e.get(i)??g;e.set(u,q),e.set(i,_),w(q,n,t,r+1),q!==_&&w(_,n,t,r+1)}else{let q=e.get(s)??g;e.set(s,q);let _=e.get(u);if(_===e.get(i)){let Z=new Map(_.entries());Z.matchIndex=_.matchIndex,e.set(i,Z)}w(q,n,t,r+1)}}}function Me(e,n,t){let r,s,u=e;for(let i=t;i<n.length;i++){let g=n[i];if(u.matchIndex!=null&&(s==null||u.matchIndex<=s)&&(r=i,s=u.matchIndex),u=u.get(g),!u)break}return u&&u.matchIndex!=null&&(s==null||u.matchIndex<=s)&&(r=n.length,s=u.matchIndex),r==null?void 0:{end:r,matchIndex:s}}});var M=a(f=>{"use strict";Object.defineProperty(f,"__esModule",{value:!0});f.toggleFusions=f.shouldPerformFusions=void 0;f.ref=Fe;f.expect=se;f.expectErase=Se;f.surely=$e;f.token=Te;f.lookaround=Ie;var h=l(),je=()=>ne;f.shouldPerformFusions=je;var ne=!0,me=e=>{ne=e};f.toggleFusions=me;function Fe(e,n,t){return r=>{let s=e(r);return!(0,h.isFailure)(s)&&!n(s.value)?(0,h.failure)(s.ctx,t??"check",[`ref: ${t??"check"}`]):s}}function se(e,n){return t=>{let r=e(t);return(0,h.isFailure)(r)?(0,h.failure)(r.ctx,n,[n,...r.history]):r}}function Se(e,n){return t=>{let r=e(t);return(0,h.isFailure)(r)?(0,h.failure)(r.ctx,n,[n]):r}}function $e(e){return se(e,"surely")}function Te(e){return n=>{let t=e(n);return t.success?{...t,value:{value:t.value,start:n.index,end:t.ctx.index}}:t}}function Ie(e){return n=>{let t=e(n);return t.success?(0,h.success)(n,void 0):(0,h.failure)(n,t.expected,["lookaround",...t.history])}}});var ue=a(R=>{"use strict";Object.defineProperty(R,"__esModule",{value:!0});R.any=ze;var D=l(),Ee=te(),Ce=M(),Be=["str","stri","anyString"];function ze(...e){let n={};if((0,Ce.shouldPerformFusions)()&&e.every(t=>"parserType"in t&&typeof t.parserType=="string"&&Be.includes(t.parserType))){let r=e.flatMap(s=>{switch(s.parserType){case"anyString":return s.matches;case"str":return[[s.match,!1]];case"stri":return[[s.match,!0]]}});if(r.length>10)return(0,Ee.anyString)(r);n={parserType:"anyString",matches:r}}return Object.assign(t=>{let r=[];for(let u of e){let i=u(t);if((0,D.isFailure)(i)){if(i.history.includes("surely"))return(0,D.failure)(i.ctx,i.expected,i.history.filter(g=>g!=="surely"));r.push(i)}else return i}let s=r.reduce((u,i)=>u.history.length>i.history.length?u:i);return(0,D.failure)(s.ctx,s.expected,["any",...s.history])},n)}});var v=a(Q=>{"use strict";Object.defineProperty(Q,"__esModule",{value:!0});Q.seq=De;var N=l();function De(...e){return n=>{let t=[];for(let r of e){let s=r(n);if(n=s.ctx,(0,N.isFailure)(s))return(0,N.failure)(s.ctx,s.expected,["seq",...s.history]);t.push(s.value)}return(0,N.success)(n,t)}}});var oe=a(A=>{"use strict";Object.defineProperty(A,"__esModule",{value:!0});A.between=Ne;var ie=l(),Re=v();function Ne(e,n,t){let r=(0,Re.seq)(e,n,t);return s=>{let u=r(s);if((0,ie.isFailure)(u)){let i=[...u.history];return i.splice(0,1),(0,ie.failure)(u.ctx,u.expected,["between",...i])}return{...u,value:u.value[1]}}}});var ce=a(H=>{"use strict";Object.defineProperty(H,"__esModule",{value:!0});H.exhaust=Qe;var P=l();function Qe(e,n=null){return t=>{let r=[];for(;;){let s=e(t);if((0,P.isFailure)(s))return n===null||(0,P.isFailure)(n(t))?(0,P.failure)(s.ctx,s.expected,["exhaust",...s.history]):(0,P.success)(t,r);if(t=s.ctx,r.push(s.value),s.ctx.index===s.ctx.text.length)return(0,P.success)(s.ctx,r)}}}});var m=a(L=>{"use strict";Object.defineProperty(L,"__esModule",{value:!0});L.map=Ae;var j=l();function Ae(e,n){return t=>{let r=e(t);if((0,j.isFailure)(r))return(0,j.failure)(r.ctx,r.expected,["map",...r.history]);try{let s=n(r.value);return(0,j.success)(r.ctx,s)}catch{return(0,j.failure)(r.ctx,"Error while mapping",["map"])}}}});var F=a(U=>{"use strict";Object.defineProperty(U,"__esModule",{value:!0});U.opt=He;var ae=l();function He(e){return n=>{let t=e(n);return(0,ae.isFailure)(t)?(0,ae.success)(n,null):t}}});var fe=a(b=>{"use strict";Object.defineProperty(b,"__esModule",{value:!0});b.many=V;b.zeroOrMany=Ue;b.oneOrMany=le;b.oneOrManyRed=Ve;var S=l(),x=m(),Le=F(),$=v();function V(e){return n=>{let t=[];for(;;){let r=e(n);if((0,S.isFailure)(r))return(0,S.success)(n,t);n=r.ctx,t.push(r.value)}}}function Ue(e,n){return(0,x.map)((0,Le.opt)(le(e,n)),t=>t??[])}function le(e,n=void 0){let t=(0,x.map)((0,$.seq)(e,V(n?(0,x.map)((0,$.seq)(n,e),([,r])=>r):e)),([r,s])=>[r,...s]);return r=>{let s=t(r);if((0,S.isFailure)(s)){let u=[...s.history];return u.splice(0,2),(0,S.failure)(s.ctx,s.expected,["oneOrMany",...u])}return s}}function Ve(e,n,t){return(0,x.map)((0,x.map)((0,$.seq)((0,x.map)(e,r=>[null,r]),V((0,$.seq)(n,e))),([r,s])=>[r,...s]),r=>{let s=r[0][1];for(let u=1;u<r.length;u++)s=t(s,r[u][1],r[u][0]);return s})}});var G=a(W=>{"use strict";Object.defineProperty(W,"__esModule",{value:!0});W.regex=We;var de=l();function We(e,n){let t=new RegExp(e,typeof e=="string"?"y":e.flags+"y");return r=>{t.lastIndex=r.index;let s=t.exec(r.text);return s!==null&&s.index===r.index?(0,de.success)({...r,index:r.index+s[0].length},s[0]):(0,de.failure)(r,n,[n])}}});var J=a(I=>{"use strict";Object.defineProperty(I,"__esModule",{value:!0});I.str=Ge;I.stri=Ke;var T=l();function Ge(e){let n=`'${e}'`;return Object.assign(t=>t.text.startsWith(e,t.index)?(0,T.success)({...t,index:t.index+e.length},e):(0,T.failure)(t,n,[n]),{parserType:"str",match:e})}var Je=new Intl.Collator("en",{sensitivity:"accent"});function Ke(e){let n=e.toLowerCase(),t=`'${n}'`;return Object.assign(r=>{let s=r.text.slice(r.index,r.index+e.length);return Je.compare(e,s)==0?(0,T.success)({...r,index:r.index+e.length},n):(0,T.failure)(r,t,[t])},{parserType:"stri",match:n})}});var ye=a(E=>{"use strict";Object.defineProperty(E,"__esModule",{value:!0});E.recoverBySkippingChars=Xe;E.recoverByAddingChars=Ye;var pe=l();function Xe(e,n){return t=>{let r=null;for(let s=0;s<=n;s++){let u=e({index:t.index+s,path:t.path,text:t.text});if((0,pe.isFailure)(u))r??=u;else return u}return r}}function Ye(e,n){return t=>{let r=null;for(let s=0;s<=n.length;s++){let u=n.slice(0,s),i=e({index:t.index,path:t.path,text:`${t.text.slice(0,t.index)}${u}${t.text.slice(t.index)}`});if((0,pe.isFailure)(i))r??=i;else return i}return r}}});var ge=a(o=>{"use strict";Object.defineProperty(o,"__esModule",{value:!0});o.eof=o.realP=o.real=o.intP=o.int=o.boolP=o.bool=o.wspaces=o.spacesPlus=o.spaces=void 0;var he=l(),C=m(),Ze=F(),O=G(),ke=v(),er=J(),rr=M();o.spaces=(0,O.regex)(/ */,"spaces");o.spacesPlus=(0,O.regex)(/ +/,"spaces");o.wspaces=(0,Ze.opt)((0,O.regex)(/(?:\s|\t|\n|\r)+/,"whitespace characters"));o.bool=(0,O.regex)(/true|false/,"boolean");o.boolP=(0,C.map)(o.bool,e=>e==="true");o.int=(0,O.regex)(/\d+/,"integer");o.intP=(0,C.map)(o.int,e=>parseInt(e,10));o.real=(0,rr.expect)((0,C.map)((0,ke.seq)(o.int,(0,er.str)("."),o.int),([e,,n])=>`${e}.${n}`),"real");o.realP=(0,C.map)(o.real,e=>parseFloat(e));var tr=e=>e.index===e.text.length?(0,he.success)(e,void 0):(0,he.failure)(e,"End Of File",["EOF"]);o.eof=tr});var qe=a(c=>{"use strict";var nr=c&&c.__createBinding||(Object.create?(function(e,n,t,r){r===void 0&&(r=t);var s=Object.getOwnPropertyDescriptor(n,t);(!s||("get"in s?!n.__esModule:s.writable||s.configurable))&&(s={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,r,s)}):(function(e,n,t,r){r===void 0&&(r=t),e[r]=n[t]})),d=c&&c.__exportStar||function(e,n){for(var t in e)t!=="default"&&!Object.prototype.hasOwnProperty.call(n,t)&&nr(n,e,t)};Object.defineProperty(c,"__esModule",{value:!0});c.stri=c.str=void 0;d(ue(),c);d(oe(),c);d(ce(),c);d(fe(),c);d(m(),c);d(F(),c);d(G(),c);d(v(),c);var _e=J();Object.defineProperty(c,"str",{enumerable:!0,get:function(){return _e.str}});Object.defineProperty(c,"stri",{enumerable:!0,get:function(){return _e.stri}});d(ye(),c);d(M(),c);d(ge(),c)});var xe=a(X=>{"use strict";Object.defineProperty(X,"__esModule",{value:!0});X.ParseText=sr;var K=l();function sr(e,n,t=""){let r=n({text:e,path:t,index:0});if((0,K.isFailure)(r))throw new K.ParseError(`Parse error, expected ${[...r.history].pop()} at char ${r.ctx.index}`,e,r.ctx.index,r.history);if(r.ctx.index!==e.length)throw new K.ParseError(`Parse error, expected end of text at char ${r.ctx.index}`,e,r.ctx.index,[]);return r.value}});var ir=a(y=>{var ur=y&&y.__createBinding||(Object.create?(function(e,n,t,r){r===void 0&&(r=t);var s=Object.getOwnPropertyDescriptor(n,t);(!s||("get"in s?!n.__esModule:s.writable||s.configurable))&&(s={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,r,s)}):(function(e,n,t,r){r===void 0&&(r=t),e[r]=n[t]})),Y=y&&y.__exportStar||function(e,n){for(var t in e)t!=="default"&&!Object.prototype.hasOwnProperty.call(n,t)&&ur(n,e,t)};Object.defineProperty(y,"__esModule",{value:!0});Y(l(),y);Y(qe(),y);Y(xe(),y)});export default ir();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";(()=>{function c(e){return!e.success}function l(e,n){return{success:!0,value:n,ctx:e}}function i(e,n,t){return{success:!1,expected:n,ctx:e,history:t}}function z(e){return n=>l(n,e)}function N(e){return n=>i(n,e,[e])}var d=class extends Error{constructor(n,t,r,s){super(n),this.index=r,this.history=s,[this.line,this.column,this.row]=this.getInputData(t,r)}getInputData(n,t){let r=n.split(`
|
|
2
|
+
`),s=0;for(;t>0;){if(r[s].length>t)return[r[s],t+1,s+1];t-=r[s].length+1,s+=1}return[r[s],t+1,s+1]}getPrettyErrorMessage(){return`${this.message} (line ${this.row}, col ${this.column}):
|
|
3
|
+
${this.line}
|
|
4
|
+
${(this.column>0?"-".repeat(this.column-1):"")+"^"}`}};function T(e){let n=`'${e[e.length-1][0]}'`,t;return Object.assign(r=>{t??=P(e);let s=S(t,r.text,r.index);return s?l({...r,index:s.end},e[s.matchIndex][0]):i(r,n,["any",n])},{parserType:"anyString",matches:e})}function P(e){let n=new Map;return e.forEach((t,r)=>g(n,t,r)),n}function g(e,n,t,r=0){if(r>=n[0].length)e.matchIndex!=null?e.matchIndex=Math.min(e.matchIndex,t):e.matchIndex=t;else{let s=n[0][r],o=s.toLowerCase(),u=s.toUpperCase(),a=new Map;if(n[1]&&o!==u){let m=e.get(o)??a,x=e.get(u)??a;e.set(o,m),e.set(u,x),g(m,n,t,r+1),m!==x&&g(x,n,t,r+1)}else{let m=e.get(s)??a;e.set(s,m);let x=e.get(o);if(x===e.get(u)){let $=new Map(x.entries());$.matchIndex=x.matchIndex,e.set(u,$)}g(m,n,t,r+1)}}}function S(e,n,t){let r,s,o=e;for(let u=t;u<n.length;u++){let a=n[u];if(o.matchIndex!=null&&(s==null||o.matchIndex<=s)&&(r=u,s=o.matchIndex),o=o.get(a),!o)break}return o&&o.matchIndex!=null&&(s==null||o.matchIndex<=s)&&(r=n.length,s=o.matchIndex),r==null?void 0:{end:r,matchIndex:s}}var I=()=>M,M=!0,H=e=>{M=e};function L(e,n,t){return r=>{let s=e(r);return!c(s)&&!n(s.value)?i(s.ctx,t??"check",[`ref: ${t??"check"}`]):s}}function w(e,n){return t=>{let r=e(t);return c(r)?i(r.ctx,n,[n,...r.history]):r}}function A(e,n){return t=>{let r=e(t);return c(r)?i(r.ctx,n,[n]):r}}function U(e){return w(e,"surely")}function V(e){return n=>{let t=e(n);return t.success?{...t,value:{value:t.value,start:n.index,end:t.ctx.index}}:t}}function W(e){return n=>{let t=e(n);return t.success?l(n,void 0):i(n,t.expected,["lookaround",...t.history])}}var O=["str","stri","anyString"];function Y(...e){let n={};if(I()&&e.every(t=>"parserType"in t&&typeof t.parserType=="string"&&O.includes(t.parserType))){let r=e.flatMap(s=>{switch(s.parserType){case"anyString":return s.matches;case"str":return[[s.match,!1]];case"stri":return[[s.match,!0]]}});if(r.length>10)return T(r);n={parserType:"anyString",matches:r}}return Object.assign(t=>{let r=[];for(let o of e){let u=o(t);if(c(u)){if(u.history.includes("surely"))return i(u.ctx,u.expected,u.history.filter(a=>a!=="surely"));r.push(u)}else return u}let s=r.reduce((o,u)=>o.history.length>u.history.length?o:u);return i(s.ctx,s.expected,["any",...s.history])},n)}function f(...e){return n=>{let t=[];for(let r of e){let s=r(n);if(n=s.ctx,c(s))return i(s.ctx,s.expected,["seq",...s.history]);t.push(s.value)}return l(n,t)}}function ne(e,n,t){let r=f(e,n,t);return s=>{let o=r(s);if(c(o)){let u=[...o.history];return u.splice(0,1),i(o.ctx,o.expected,["between",...u])}return{...o,value:o.value[1]}}}function ie(e,n=null){return t=>{let r=[];for(;;){let s=e(t);if(c(s))return n===null||c(n(t))?i(s.ctx,s.expected,["exhaust",...s.history]):l(t,r);if(t=s.ctx,r.push(s.value),s.ctx.index===s.ctx.text.length)return l(s.ctx,r)}}}function p(e,n){return t=>{let r=e(t);if(c(r))return i(r.ctx,r.expected,["map",...r.history]);try{let s=n(r.value);return l(r.ctx,s)}catch{return i(r.ctx,"Error while mapping",["map"])}}}function y(e){return n=>{let t=e(n);return c(t)?l(n,null):t}}function b(e){return n=>{let t=[];for(;;){let r=e(n);if(c(r))return l(n,t);n=r.ctx,t.push(r.value)}}}function de(e,n){return p(y(k(e,n)),t=>t??[])}function k(e,n=void 0){let t=p(f(e,b(n?p(f(n,e),([,r])=>r):e)),([r,s])=>[r,...s]);return r=>{let s=t(r);if(c(s)){let o=[...s.history];return o.splice(0,2),i(s.ctx,s.expected,["oneOrMany",...o])}return s}}function ge(e,n,t){return p(p(f(p(e,r=>[null,r]),b(f(n,e))),([r,s])=>[r,...s]),r=>{let s=r[0][1];for(let o=1;o<r.length;o++)s=t(s,r[o][1],r[o][0]);return s})}function h(e,n){let t=new RegExp(e,typeof e=="string"?"y":e.flags+"y");return r=>{t.lastIndex=r.index;let s=t.exec(r.text);return s!==null&&s.index===r.index?l({...r,index:r.index+s[0].length},s[0]):i(r,n,[n])}}function F(e){let n=`'${e}'`;return Object.assign(t=>t.text.startsWith(e,t.index)?l({...t,index:t.index+e.length},e):i(t,n,[n]),{parserType:"str",match:e})}var E=new Intl.Collator("en",{sensitivity:"accent"});function q(e){let n=e.toLowerCase(),t=`'${n}'`;return Object.assign(r=>{let s=r.text.slice(r.index,r.index+e.length);return E.compare(e,s)==0?l({...r,index:r.index+e.length},n):i(r,t,[t])},{parserType:"stri",match:n})}function Ie(e,n){return t=>{let r=null;for(let s=0;s<=n;s++){let o=e({index:t.index+s,path:t.path,text:t.text});if(c(o))r??=o;else return o}return r}}function Me(e,n){return t=>{let r=null;for(let s=0;s<=n.length;s++){let o=n.slice(0,s),u=e({index:t.index,path:t.path,text:`${t.text.slice(0,t.index)}${o}${t.text.slice(t.index)}`});if(c(u))r??=u;else return u}return r}}var je=h(/ */,"spaces"),ze=h(/ +/,"spaces"),Ne=y(h(/(?:\s|\t|\n|\r)+/,"whitespace characters")),C=h(/true|false/,"boolean"),Qe=p(C,e=>e==="true"),v=h(/\d+/,"integer"),Re=p(v,e=>parseInt(e,10)),j=w(p(f(v,F("."),v),([e,,n])=>`${e}.${n}`),"real"),Be=p(j,e=>parseFloat(e)),De=e=>e.index===e.text.length?l(e,void 0):i(e,"End Of File",["EOF"]);function tr(e,n,t=""){let r=n({text:e,path:t,index:0});if(c(r))throw new d(`Parse error, expected ${[...r.history].pop()} at char ${r.ctx.index}`,e,r.ctx.index,r.history);if(r.ctx.index!==e.length)throw new d(`Parse error, expected end of text at char ${r.ctx.index}`,e,r.ctx.index,[]);return r.value}})();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Parser } from './types';
|
|
2
|
+
/** Parses the given string.
|
|
3
|
+
* @param text The string to parse.
|
|
4
|
+
* @param parser The parser to use.
|
|
5
|
+
* @param path The path of the parsed text. Can be used for error reporting.
|
|
6
|
+
* @returns The result of the parse.
|
|
7
|
+
* @throws {ParseError} if the parsing fails or the parser does not consume the full input.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ParseText<T>(text: string, parser: Parser<T>, path?: string): T;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isFailure, ParseError } from './types';
|
|
2
|
+
/** Parses the given string.
|
|
3
|
+
* @param text The string to parse.
|
|
4
|
+
* @param parser The parser to use.
|
|
5
|
+
* @param path The path of the parsed text. Can be used for error reporting.
|
|
6
|
+
* @returns The result of the parse.
|
|
7
|
+
* @throws {ParseError} if the parsing fails or the parser does not consume the full input.
|
|
8
|
+
*/
|
|
9
|
+
export function ParseText(text, parser, path = '') {
|
|
10
|
+
const res = parser({ text, path, index: 0 });
|
|
11
|
+
if (isFailure(res)) {
|
|
12
|
+
throw new ParseError(`Parse error, expected ${[...res.history].pop()} at char ${res.ctx.index}`, text, res.ctx.index, res.history);
|
|
13
|
+
}
|
|
14
|
+
if (res.ctx.index !== text.length) {
|
|
15
|
+
throw new ParseError(`Parse error, expected end of text at char ${res.ctx.index}`, text, res.ctx.index, []);
|
|
16
|
+
}
|
|
17
|
+
return res.value;
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
/** Parses the input using any passed parser, trying from left to right.
|
|
3
|
+
* @returns A parser returning the result of the first parser that succeeds, or the failure that has come the furthest.
|
|
4
|
+
*/
|
|
5
|
+
export declare function any<T, U, V, W, X, Z, I, J, K, L, M>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>, Parser<K>, Parser<L>, Parser<M>]): Parser<T | U | V | W | X | Z | I | J | K | L | M>;
|
|
6
|
+
export declare function any<T, U, V, W, X, Z, I, J, K, L>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>, Parser<K>, Parser<L>]): Parser<T | U | V | W | X | Z | I | J | K | L>;
|
|
7
|
+
export declare function any<T, U, V, W, X, Z, I, J, K>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>, Parser<K>]): Parser<T | U | V | W | X | Z | I | J | K>;
|
|
8
|
+
export declare function any<T, U, V, W, X, Z, I, J>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>]): Parser<T | U | V | W | X | Z | I | J>;
|
|
9
|
+
export declare function any<T, U, V, W, X, Z, I>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>]): Parser<T | U | V | W | X | Z | I>;
|
|
10
|
+
export declare function any<T, U, V, W, X, Z>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>]): Parser<T | U | V | W | X | Z>;
|
|
11
|
+
export declare function any<T, U, V, W, X>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>]): Parser<T | U | V | W | X>;
|
|
12
|
+
export declare function any<T, U, V, W>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>]): Parser<T | U | V | W>;
|
|
13
|
+
export declare function any<T, U, V>(...parsers: [Parser<T>, Parser<U>, Parser<V>]): Parser<T | U | V>;
|
|
14
|
+
export declare function any<T, U>(...parsers: [Parser<T>, Parser<U>]): Parser<T | U>;
|
|
15
|
+
export declare function any<T>(...parsers: [Parser<T>]): Parser<T>;
|
|
16
|
+
export declare function any<T>(...parsers: Parser<T>[]): Parser<T>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { failure, isFailure } from '../types';
|
|
2
|
+
import { anyString } from './anyString';
|
|
3
|
+
import { shouldPerformFusions } from './utilities';
|
|
4
|
+
const optimizableTypes = ['str', 'stri', 'anyString'];
|
|
5
|
+
export function any(...parsers) {
|
|
6
|
+
let marker = {};
|
|
7
|
+
if (shouldPerformFusions() && parsers.every(p => 'parserType' in p && typeof p.parserType === 'string' && optimizableTypes.includes(p.parserType))) {
|
|
8
|
+
const optimizableParsers = parsers;
|
|
9
|
+
const matches = optimizableParsers.flatMap(p => {
|
|
10
|
+
switch (p.parserType) {
|
|
11
|
+
case 'anyString':
|
|
12
|
+
return p.matches;
|
|
13
|
+
case 'str':
|
|
14
|
+
return [[p.match, false]];
|
|
15
|
+
case 'stri':
|
|
16
|
+
return [[p.match, true]];
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
// Not fusing if not enough matches
|
|
20
|
+
// We do pass the matches forward though, because a parser above may want to fuse
|
|
21
|
+
if (matches.length > 10) {
|
|
22
|
+
return anyString(matches);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
marker = { parserType: 'anyString', matches };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return Object.assign((ctx) => {
|
|
29
|
+
const expected = [];
|
|
30
|
+
for (const parser of parsers) {
|
|
31
|
+
const res = parser(ctx);
|
|
32
|
+
if (isFailure(res)) {
|
|
33
|
+
if (res.history.includes('surely')) {
|
|
34
|
+
return failure(res.ctx, res.expected, res.history.filter(h => h !== 'surely'));
|
|
35
|
+
}
|
|
36
|
+
expected.push(res);
|
|
37
|
+
}
|
|
38
|
+
else
|
|
39
|
+
return res;
|
|
40
|
+
}
|
|
41
|
+
const longest = expected.reduce((a, b) => a.history.length > b.history.length ? a : b);
|
|
42
|
+
return failure(longest.ctx, longest.expected, ['any', ...longest.history]);
|
|
43
|
+
}, marker);
|
|
44
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
import { StrIParser, StrParser } from "./str";
|
|
3
|
+
type AnyStringParser<T> = Parser<T> & {
|
|
4
|
+
parserType: 'anyString';
|
|
5
|
+
/**
|
|
6
|
+
* if flag is true, match case-insensitive
|
|
7
|
+
*/
|
|
8
|
+
matches: (readonly [string, boolean])[];
|
|
9
|
+
};
|
|
10
|
+
export type OptimizableStrParser<T> = AnyStringParser<T> | StrParser<T> | StrIParser<T>;
|
|
11
|
+
/**
|
|
12
|
+
* Optimization for `any(str(), str(), ...)` which replaces the parser tree with one parser which tries all strings together
|
|
13
|
+
*/
|
|
14
|
+
export declare function anyString<T extends string>(matches: (readonly [string, boolean])[]): AnyStringParser<T>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { failure, success } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Optimization for `any(str(), str(), ...)` which replaces the parser tree with one parser which tries all strings together
|
|
4
|
+
*/
|
|
5
|
+
export function anyString(matches) {
|
|
6
|
+
const lastMatchInQuotes = `'${matches[matches.length - 1][0]}'`;
|
|
7
|
+
let tree;
|
|
8
|
+
return Object.assign((ctx) => {
|
|
9
|
+
tree ??= createSearchTree(matches);
|
|
10
|
+
const result = searchThroughTree(tree, ctx.text, ctx.index);
|
|
11
|
+
if (result) {
|
|
12
|
+
return success({ ...ctx, index: result.end }, matches[result.matchIndex][0]);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return failure(ctx, lastMatchInQuotes, ['any', lastMatchInQuotes]);
|
|
16
|
+
}
|
|
17
|
+
}, { parserType: 'anyString', matches });
|
|
18
|
+
}
|
|
19
|
+
function createSearchTree(matches) {
|
|
20
|
+
const tree = new Map();
|
|
21
|
+
matches.forEach((match, index) => addMatchToTree(tree, match, index));
|
|
22
|
+
return tree;
|
|
23
|
+
}
|
|
24
|
+
function addMatchToTree(node, match, idIndex, charIndex = 0) {
|
|
25
|
+
if (charIndex >= match[0].length) {
|
|
26
|
+
if (node.matchIndex != undefined) {
|
|
27
|
+
node.matchIndex = Math.min(node.matchIndex, idIndex);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
node.matchIndex = idIndex;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const char = match[0][charIndex];
|
|
35
|
+
const lowercase = char.toLowerCase();
|
|
36
|
+
const uppercase = char.toUpperCase();
|
|
37
|
+
const newNode = new Map();
|
|
38
|
+
if (match[1] && (lowercase !== uppercase)) {
|
|
39
|
+
const lower = node.get(lowercase) ?? newNode;
|
|
40
|
+
const upper = node.get(uppercase) ?? newNode;
|
|
41
|
+
node.set(lowercase, lower);
|
|
42
|
+
node.set(uppercase, upper);
|
|
43
|
+
addMatchToTree(lower, match, idIndex, charIndex + 1);
|
|
44
|
+
if (lower !== upper) {
|
|
45
|
+
addMatchToTree(upper, match, idIndex, charIndex + 1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const charNode = node.get(char) ?? newNode;
|
|
50
|
+
node.set(char, charNode);
|
|
51
|
+
const lower = node.get(lowercase);
|
|
52
|
+
if (lower === node.get(uppercase)) {
|
|
53
|
+
const copy = new Map(lower.entries());
|
|
54
|
+
copy.matchIndex = lower.matchIndex;
|
|
55
|
+
node.set(uppercase, copy);
|
|
56
|
+
}
|
|
57
|
+
addMatchToTree(charNode, match, idIndex, charIndex + 1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function searchThroughTree(node, text, start) {
|
|
62
|
+
let lastSuccessIndex = undefined;
|
|
63
|
+
let lastSuccessMatchIndex = undefined;
|
|
64
|
+
let currentNode = node;
|
|
65
|
+
for (let index = start; index < text.length; index++) {
|
|
66
|
+
const char = text[index];
|
|
67
|
+
if (currentNode.matchIndex != undefined && (lastSuccessMatchIndex == undefined || currentNode.matchIndex <= lastSuccessMatchIndex)) {
|
|
68
|
+
lastSuccessIndex = index;
|
|
69
|
+
lastSuccessMatchIndex = currentNode.matchIndex;
|
|
70
|
+
}
|
|
71
|
+
currentNode = currentNode.get(char);
|
|
72
|
+
if (!currentNode)
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (currentNode && currentNode.matchIndex != undefined && (lastSuccessMatchIndex == undefined || currentNode.matchIndex <= lastSuccessMatchIndex)) {
|
|
76
|
+
lastSuccessIndex = text.length;
|
|
77
|
+
lastSuccessMatchIndex = currentNode.matchIndex;
|
|
78
|
+
}
|
|
79
|
+
return lastSuccessIndex == undefined
|
|
80
|
+
? undefined
|
|
81
|
+
: { end: lastSuccessIndex, matchIndex: lastSuccessMatchIndex };
|
|
82
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { failure, isFailure } from '../types';
|
|
2
|
+
import { seq } from './seq';
|
|
3
|
+
/** Parses a sequence of three parsers.
|
|
4
|
+
* @returns A parser returning only the middle parser's result.
|
|
5
|
+
*/
|
|
6
|
+
export function between(left, parser, right) {
|
|
7
|
+
const sequence = seq(left, parser, right);
|
|
8
|
+
return (ctx) => {
|
|
9
|
+
const res = sequence(ctx);
|
|
10
|
+
if (isFailure(res)) {
|
|
11
|
+
const newHistory = [...res.history];
|
|
12
|
+
newHistory.splice(0, 1);
|
|
13
|
+
return failure(res.ctx, res.expected, ['between', ...newHistory]);
|
|
14
|
+
}
|
|
15
|
+
return { ...res, value: res.value[1] };
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
/** Parses using the passed in parser, until the input is exhausted or until the `until` condition is satisfied.
|
|
3
|
+
* @returns A parser returning an array of parsed results.
|
|
4
|
+
*/
|
|
5
|
+
export declare function exhaust<T, V>(parser: Parser<T>, until?: Parser<V> | null): Parser<T[]>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { failure, isFailure, success } from '../types';
|
|
2
|
+
/** Parses using the passed in parser, until the input is exhausted or until the `until` condition is satisfied.
|
|
3
|
+
* @returns A parser returning an array of parsed results.
|
|
4
|
+
*/
|
|
5
|
+
export function exhaust(parser, until = null) {
|
|
6
|
+
return (ctx) => {
|
|
7
|
+
const results = [];
|
|
8
|
+
while (true) {
|
|
9
|
+
const res = parser(ctx);
|
|
10
|
+
if (isFailure(res)) {
|
|
11
|
+
if (until === null || isFailure(until(ctx))) {
|
|
12
|
+
return failure(res.ctx, res.expected, ['exhaust', ...res.history]);
|
|
13
|
+
}
|
|
14
|
+
return success(ctx, results);
|
|
15
|
+
}
|
|
16
|
+
ctx = res.ctx;
|
|
17
|
+
results.push(res.value);
|
|
18
|
+
if (res.ctx.index === res.ctx.text.length)
|
|
19
|
+
return success(res.ctx, results);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './any';
|
|
2
|
+
export * from './between';
|
|
3
|
+
export * from './exhaust';
|
|
4
|
+
export * from './many';
|
|
5
|
+
export * from './map';
|
|
6
|
+
export * from './opt';
|
|
7
|
+
export * from './regex';
|
|
8
|
+
export * from './seq';
|
|
9
|
+
export { str, stri } from './str';
|
|
10
|
+
export * from './recovery';
|
|
11
|
+
export * from './utilities';
|
|
12
|
+
export * from './values';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './any';
|
|
2
|
+
export * from './between';
|
|
3
|
+
export * from './exhaust';
|
|
4
|
+
export * from './many';
|
|
5
|
+
export * from './map';
|
|
6
|
+
export * from './opt';
|
|
7
|
+
export * from './regex';
|
|
8
|
+
export * from './seq';
|
|
9
|
+
export { str, stri } from './str';
|
|
10
|
+
export * from './recovery';
|
|
11
|
+
export * from './utilities';
|
|
12
|
+
export * from './values';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
/** Parses zero or more occurences of the given parser.
|
|
3
|
+
* @returns A parser returning an array of many parses.
|
|
4
|
+
*/
|
|
5
|
+
export declare function many<T>(parser: Parser<T>): Parser<T[]>;
|
|
6
|
+
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
7
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
8
|
+
*/
|
|
9
|
+
export declare function zeroOrMany<T, V>(item: Parser<T>, separator: Parser<V>): Parser<T[]>;
|
|
10
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
11
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
12
|
+
*/
|
|
13
|
+
export declare function oneOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
14
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
15
|
+
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
16
|
+
*/
|
|
17
|
+
export declare function oneOrManyRed<T, V, U = T>(item: Parser<T>, separator: Parser<V>, reducer: (left: U | T, right: T, sep: V) => U): Parser<U | T>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { failure, isFailure, success } from '../types';
|
|
2
|
+
import { map } from './map';
|
|
3
|
+
import { opt } from './opt';
|
|
4
|
+
import { seq } from './seq';
|
|
5
|
+
/** Parses zero or more occurences of the given parser.
|
|
6
|
+
* @returns A parser returning an array of many parses.
|
|
7
|
+
*/
|
|
8
|
+
export function many(parser) {
|
|
9
|
+
return (ctx) => {
|
|
10
|
+
const results = [];
|
|
11
|
+
while (true) {
|
|
12
|
+
const res = parser(ctx);
|
|
13
|
+
if (isFailure(res)) {
|
|
14
|
+
return success(ctx, results);
|
|
15
|
+
}
|
|
16
|
+
ctx = res.ctx;
|
|
17
|
+
results.push(res.value);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
22
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
23
|
+
*/
|
|
24
|
+
export function zeroOrMany(item, separator) {
|
|
25
|
+
return map(opt(oneOrMany(item, separator)), t => t ?? []);
|
|
26
|
+
}
|
|
27
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
28
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
29
|
+
*/
|
|
30
|
+
export function oneOrMany(item, separator = undefined) {
|
|
31
|
+
const sequencer = map(seq(item, many(separator
|
|
32
|
+
? map(seq(separator, item), ([, t]) => t)
|
|
33
|
+
: item)), ([t, ts]) => ([t, ...ts]));
|
|
34
|
+
return (ctx) => {
|
|
35
|
+
const res = sequencer(ctx);
|
|
36
|
+
if (isFailure(res)) {
|
|
37
|
+
const newHistory = [...res.history];
|
|
38
|
+
newHistory.splice(0, 2);
|
|
39
|
+
return failure(res.ctx, res.expected, ['oneOrMany', ...newHistory]);
|
|
40
|
+
}
|
|
41
|
+
return res;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
45
|
+
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
46
|
+
*/
|
|
47
|
+
export function oneOrManyRed(item, separator, reducer) {
|
|
48
|
+
return map(map(seq(map(item, (x) => [null, x]), many(seq(separator, item))), ([t, ts]) => ([t, ...ts])), ts => {
|
|
49
|
+
let result = ts[0][1];
|
|
50
|
+
for (let i = 1; i < ts.length; i++) {
|
|
51
|
+
result = reducer(result, ts[i][1], ts[i][0]);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
/** Parses the input using the given parser, then maps the output.
|
|
3
|
+
* @returns A parser that parses the same input, but has output mapped using the mapping function.
|
|
4
|
+
*/
|
|
5
|
+
export declare function map<A, B>(parser: Parser<A>, mapper: (val: A) => B): Parser<B>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { failure, isFailure, success } from '../types';
|
|
2
|
+
/** Parses the input using the given parser, then maps the output.
|
|
3
|
+
* @returns A parser that parses the same input, but has output mapped using the mapping function.
|
|
4
|
+
*/
|
|
5
|
+
export function map(parser, mapper) {
|
|
6
|
+
return (ctx) => {
|
|
7
|
+
const res = parser(ctx);
|
|
8
|
+
if (isFailure(res))
|
|
9
|
+
return failure(res.ctx, res.expected, ['map', ...res.history]);
|
|
10
|
+
try {
|
|
11
|
+
const newValue = mapper(res.value);
|
|
12
|
+
return success(res.ctx, newValue);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return failure(res.ctx, 'Error while mapping', ['map']);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { isFailure, success } from '../types';
|
|
2
|
+
/** Makes the parser optional.
|
|
3
|
+
* @returns A parser that succeeds with `null` result if the parsing didn't succeed.
|
|
4
|
+
*/
|
|
5
|
+
export function opt(parser) {
|
|
6
|
+
return (ctx) => {
|
|
7
|
+
const parseResult = parser(ctx);
|
|
8
|
+
if (isFailure(parseResult)) {
|
|
9
|
+
return success(ctx, null);
|
|
10
|
+
}
|
|
11
|
+
return parseResult;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Tries to automatically recover a parsing failure by removing characters from the front.
|
|
4
|
+
*
|
|
5
|
+
* If the inner parser fails, the recovery parser will restart parsing skipping a character, up to {@link chars} skips
|
|
6
|
+
*/
|
|
7
|
+
export declare function recoverBySkippingChars<T>(parser: Parser<T>, chars: number): Parser<T>;
|
|
8
|
+
/**
|
|
9
|
+
* Tries to automatically recover a parsing failure by adding characters to the front.
|
|
10
|
+
*
|
|
11
|
+
* If the inner parser fails, the recovery parser will restart parsing adding a character, up to {@link chars}
|
|
12
|
+
* @todo Inserting characters in the middle of a context string is inefficient - maybe there's a better way?
|
|
13
|
+
*/
|
|
14
|
+
export declare function recoverByAddingChars<T>(parser: Parser<T>, chars: string): Parser<T>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { isFailure } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Tries to automatically recover a parsing failure by removing characters from the front.
|
|
4
|
+
*
|
|
5
|
+
* If the inner parser fails, the recovery parser will restart parsing skipping a character, up to {@link chars} skips
|
|
6
|
+
*/
|
|
7
|
+
export function recoverBySkippingChars(parser, chars) {
|
|
8
|
+
return (ctx) => {
|
|
9
|
+
let firstFailure = null;
|
|
10
|
+
for (let i = 0; i <= chars; i++) {
|
|
11
|
+
const result = parser({
|
|
12
|
+
index: ctx.index + i,
|
|
13
|
+
path: ctx.path,
|
|
14
|
+
text: ctx.text,
|
|
15
|
+
});
|
|
16
|
+
if (isFailure(result)) {
|
|
17
|
+
firstFailure ??= result;
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
return firstFailure;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Tries to automatically recover a parsing failure by adding characters to the front.
|
|
27
|
+
*
|
|
28
|
+
* If the inner parser fails, the recovery parser will restart parsing adding a character, up to {@link chars}
|
|
29
|
+
* @todo Inserting characters in the middle of a context string is inefficient - maybe there's a better way?
|
|
30
|
+
*/
|
|
31
|
+
export function recoverByAddingChars(parser, chars) {
|
|
32
|
+
return (ctx) => {
|
|
33
|
+
let firstFailure = null;
|
|
34
|
+
for (let i = 0; i <= chars.length; i++) {
|
|
35
|
+
const addedChars = chars.slice(0, i);
|
|
36
|
+
const result = parser({
|
|
37
|
+
index: ctx.index,
|
|
38
|
+
path: ctx.path,
|
|
39
|
+
text: `${ctx.text.slice(0, ctx.index)}${addedChars}${ctx.text.slice(ctx.index)}`,
|
|
40
|
+
});
|
|
41
|
+
if (isFailure(result)) {
|
|
42
|
+
firstFailure ??= result;
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
return firstFailure;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { failure, success } from '../types';
|
|
2
|
+
/** Parses a regex and returns the matched result of the parse.
|
|
3
|
+
* @returns A parser parsing a given regex and returning a match.
|
|
4
|
+
*/
|
|
5
|
+
export function regex(match, expected) {
|
|
6
|
+
const regexp = new RegExp(match, typeof match === 'string' ? 'y' : match.flags + 'y');
|
|
7
|
+
return (ctx) => {
|
|
8
|
+
regexp.lastIndex = ctx.index;
|
|
9
|
+
const regexMatch = regexp.exec(ctx.text);
|
|
10
|
+
if (regexMatch !== null && regexMatch.index === ctx.index) {
|
|
11
|
+
return success({ ...ctx, index: ctx.index + regexMatch[0].length }, regexMatch[0]);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return failure(ctx, expected, [expected]);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
/** Parses a sequence of parsers going from left to right, returning the results of the parsers.
|
|
3
|
+
* @returns A parser parsing the sequence of parsers.
|
|
4
|
+
*/
|
|
5
|
+
export declare function seq<T, U, V, W, X, Z, I, J, K, L, M>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>, Parser<K>, Parser<L>, Parser<M>]): Parser<[T, U, V, W, X, Z, I, J, K, L, M]>;
|
|
6
|
+
export declare function seq<T, U, V, W, X, Z, I, J, K, L>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>, Parser<K>, Parser<L>]): Parser<[T, U, V, W, X, Z, I, J, K, L]>;
|
|
7
|
+
export declare function seq<T, U, V, W, X, Z, I, J, K>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>, Parser<K>]): Parser<[T, U, V, W, X, Z, I, J, K]>;
|
|
8
|
+
export declare function seq<T, U, V, W, X, Z, I, J>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>, Parser<J>]): Parser<[T, U, V, W, X, Z, I, J]>;
|
|
9
|
+
export declare function seq<T, U, V, W, X, Z, I>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>, Parser<I>]): Parser<[T, U, V, W, X, Z, I]>;
|
|
10
|
+
export declare function seq<T, U, V, W, X, Z>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>, Parser<Z>]): Parser<[T, U, V, W, X, Z]>;
|
|
11
|
+
export declare function seq<T, U, V, W, X>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>, Parser<X>]): Parser<[T, U, V, W, X]>;
|
|
12
|
+
export declare function seq<T, U, V, W>(...parsers: [Parser<T>, Parser<U>, Parser<V>, Parser<W>]): Parser<[T, U, V, W]>;
|
|
13
|
+
export declare function seq<T, U, V>(...parsers: [Parser<T>, Parser<U>, Parser<V>]): Parser<[T, U, V]>;
|
|
14
|
+
export declare function seq<T, U>(...parsers: [Parser<T>, Parser<U>]): Parser<[T, U]>;
|
|
15
|
+
export declare function seq<T>(...parsers: [Parser<T>]): Parser<[T]>;
|
|
16
|
+
export declare function seq<T>(...parsers: Parser<T>[]): Parser<T[]>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { failure, isFailure, success } from '../types';
|
|
2
|
+
export function seq(...parsers) {
|
|
3
|
+
return (ctx) => {
|
|
4
|
+
const values = [];
|
|
5
|
+
for (const parser of parsers) {
|
|
6
|
+
const res = parser(ctx);
|
|
7
|
+
ctx = res.ctx;
|
|
8
|
+
if (isFailure(res))
|
|
9
|
+
return failure(res.ctx, res.expected, ['seq', ...res.history]);
|
|
10
|
+
values.push(res.value);
|
|
11
|
+
}
|
|
12
|
+
return success(ctx, values);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
export type StrParser<T> = Parser<T> & {
|
|
3
|
+
parserType: 'str';
|
|
4
|
+
match: T;
|
|
5
|
+
};
|
|
6
|
+
/** Parses a string and returns it as a result of the parse.
|
|
7
|
+
* @returns A parser parsing a given string, case-sensitive.
|
|
8
|
+
*/
|
|
9
|
+
export declare function str<T extends string>(match: T): StrParser<T>;
|
|
10
|
+
export type StrIParser<T> = Parser<T> & {
|
|
11
|
+
parserType: 'stri';
|
|
12
|
+
match: T;
|
|
13
|
+
};
|
|
14
|
+
/** Parses a string case-insensitively and returns it as a result of the parse.
|
|
15
|
+
* @returns A parser parsing a given string, case-insensitive.
|
|
16
|
+
*/
|
|
17
|
+
export declare function stri<T extends string>(match: T): StrIParser<Lowercase<T>>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { failure, success } from '../types';
|
|
2
|
+
/** Parses a string and returns it as a result of the parse.
|
|
3
|
+
* @returns A parser parsing a given string, case-sensitive.
|
|
4
|
+
*/
|
|
5
|
+
export function str(match) {
|
|
6
|
+
const inQuotes = `'${match}'`;
|
|
7
|
+
return Object.assign((ctx) => {
|
|
8
|
+
if (ctx.text.startsWith(match, ctx.index)) {
|
|
9
|
+
return success({ ...ctx, index: ctx.index + match.length }, match);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return failure(ctx, inQuotes, [inQuotes]);
|
|
13
|
+
}
|
|
14
|
+
}, { parserType: 'str', match });
|
|
15
|
+
}
|
|
16
|
+
const collator = new Intl.Collator('en', { sensitivity: 'accent' });
|
|
17
|
+
/** Parses a string case-insensitively and returns it as a result of the parse.
|
|
18
|
+
* @returns A parser parsing a given string, case-insensitive.
|
|
19
|
+
*/
|
|
20
|
+
export function stri(match) {
|
|
21
|
+
const lowercase = match.toLowerCase();
|
|
22
|
+
const inQuotes = `'${lowercase}'`;
|
|
23
|
+
return Object.assign((ctx) => {
|
|
24
|
+
const textSlice = ctx.text.slice(ctx.index, ctx.index + match.length);
|
|
25
|
+
if (collator.compare(match, textSlice) == 0) {
|
|
26
|
+
return success({ ...ctx, index: ctx.index + match.length }, lowercase);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return failure(ctx, inQuotes, [inQuotes]);
|
|
30
|
+
}
|
|
31
|
+
}, { parserType: 'stri', match: lowercase });
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Parser, Token } from '../types';
|
|
2
|
+
export declare const shouldPerformFusions: () => boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Disables all parser combinator fusions.
|
|
5
|
+
*
|
|
6
|
+
* Should probably be used only for testing performance.
|
|
7
|
+
*/
|
|
8
|
+
export declare const toggleFusions: (value: boolean) => void;
|
|
9
|
+
/** Allows to make a condition on the result of the parsing function.
|
|
10
|
+
* @returns A parser returning the same but also performing a given check on the result.
|
|
11
|
+
*/
|
|
12
|
+
export declare function ref<T>(parser: Parser<T>, check: ((p: T) => boolean), expected?: string): Parser<T>;
|
|
13
|
+
/** Changes the expected value for when the parser fails.
|
|
14
|
+
* @returns A parser returning the same but with a different expected value.
|
|
15
|
+
*/
|
|
16
|
+
export declare function expect<T>(parser: Parser<T>, expected: string): Parser<T>;
|
|
17
|
+
/** Changes the expected value for when the parser fails. Erases the previous history.
|
|
18
|
+
* @returns A parser returning the same but with a different expected value.
|
|
19
|
+
*/
|
|
20
|
+
export declare function expectErase<T>(parser: Parser<T>, expected: string): Parser<T>;
|
|
21
|
+
/**
|
|
22
|
+
* Marks a parser as a branch that has to be executed to the end by the {@link any} parser
|
|
23
|
+
*/
|
|
24
|
+
export declare function surely<T>(parser: Parser<T>): Parser<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Wraps the value returned by the parser with the token information (the start and end index in the text)
|
|
27
|
+
* @returns A parser returning the value wrapped in token information.
|
|
28
|
+
*/
|
|
29
|
+
export declare function token<T>(parser: Parser<T>): Parser<Token<T>>;
|
|
30
|
+
/**
|
|
31
|
+
* Checks whether the parser parses successfully, but doesn't move the cursor forward
|
|
32
|
+
*/
|
|
33
|
+
export declare function lookaround<T>(parser: Parser<T>): Parser<void>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { failure, isFailure, success } from '../types';
|
|
2
|
+
export const shouldPerformFusions = () => performFusions;
|
|
3
|
+
let performFusions = true;
|
|
4
|
+
/**
|
|
5
|
+
* Disables all parser combinator fusions.
|
|
6
|
+
*
|
|
7
|
+
* Should probably be used only for testing performance.
|
|
8
|
+
*/
|
|
9
|
+
export const toggleFusions = (value) => {
|
|
10
|
+
performFusions = value;
|
|
11
|
+
};
|
|
12
|
+
/** Allows to make a condition on the result of the parsing function.
|
|
13
|
+
* @returns A parser returning the same but also performing a given check on the result.
|
|
14
|
+
*/
|
|
15
|
+
export function ref(parser, check, expected) {
|
|
16
|
+
return (ctx) => {
|
|
17
|
+
const res = parser(ctx);
|
|
18
|
+
if (!isFailure(res) && !check(res.value)) {
|
|
19
|
+
return failure(res.ctx, expected ?? 'check', [`ref: ${expected ?? 'check'}`]);
|
|
20
|
+
}
|
|
21
|
+
return res;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Changes the expected value for when the parser fails.
|
|
25
|
+
* @returns A parser returning the same but with a different expected value.
|
|
26
|
+
*/
|
|
27
|
+
export function expect(parser, expected) {
|
|
28
|
+
return (ctx) => {
|
|
29
|
+
const res = parser(ctx);
|
|
30
|
+
if (isFailure(res)) {
|
|
31
|
+
return failure(res.ctx, expected, [expected, ...res.history]);
|
|
32
|
+
}
|
|
33
|
+
return res;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Changes the expected value for when the parser fails. Erases the previous history.
|
|
37
|
+
* @returns A parser returning the same but with a different expected value.
|
|
38
|
+
*/
|
|
39
|
+
export function expectErase(parser, expected) {
|
|
40
|
+
return (ctx) => {
|
|
41
|
+
const res = parser(ctx);
|
|
42
|
+
if (isFailure(res)) {
|
|
43
|
+
return failure(res.ctx, expected, [expected]);
|
|
44
|
+
}
|
|
45
|
+
return res;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Marks a parser as a branch that has to be executed to the end by the {@link any} parser
|
|
50
|
+
*/
|
|
51
|
+
export function surely(parser) {
|
|
52
|
+
return expect(parser, 'surely');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Wraps the value returned by the parser with the token information (the start and end index in the text)
|
|
56
|
+
* @returns A parser returning the value wrapped in token information.
|
|
57
|
+
*/
|
|
58
|
+
export function token(parser) {
|
|
59
|
+
return (ctx) => {
|
|
60
|
+
const result = parser(ctx);
|
|
61
|
+
if (result.success) {
|
|
62
|
+
return {
|
|
63
|
+
...result,
|
|
64
|
+
value: {
|
|
65
|
+
value: result.value,
|
|
66
|
+
start: ctx.index,
|
|
67
|
+
end: result.ctx.index
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Checks whether the parser parses successfully, but doesn't move the cursor forward
|
|
76
|
+
*/
|
|
77
|
+
export function lookaround(parser) {
|
|
78
|
+
return (ctx) => {
|
|
79
|
+
const result = parser(ctx);
|
|
80
|
+
if (result.success) {
|
|
81
|
+
return success(ctx, void 0);
|
|
82
|
+
}
|
|
83
|
+
return failure(ctx, result.expected, ['lookaround', ...result.history]);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Parser } from '../types';
|
|
2
|
+
/** Parses 0 or more spaces
|
|
3
|
+
*/
|
|
4
|
+
export declare const spaces: Parser<string>;
|
|
5
|
+
/** Parses 1 or more spaces
|
|
6
|
+
*/
|
|
7
|
+
export declare const spacesPlus: Parser<string>;
|
|
8
|
+
/** Parses 0 or more whitespace characters
|
|
9
|
+
*/
|
|
10
|
+
export declare const wspaces: Parser<string | null>;
|
|
11
|
+
/** Parses a boolean (true or false) and returns a string
|
|
12
|
+
*/
|
|
13
|
+
export declare const bool: Parser<'true' | 'false'>;
|
|
14
|
+
/** Parses a boolean (true or false) and returns a boolean
|
|
15
|
+
*/
|
|
16
|
+
export declare const boolP: Parser<boolean>;
|
|
17
|
+
/** Parses an integer and returns a string
|
|
18
|
+
*/
|
|
19
|
+
export declare const int: Parser<string>;
|
|
20
|
+
/** Parses an integer and returns a number
|
|
21
|
+
*/
|
|
22
|
+
export declare const intP: Parser<number>;
|
|
23
|
+
/** Parses a standard real number (X.X) and returns a string
|
|
24
|
+
*/
|
|
25
|
+
export declare const real: Parser<`${number}.${number}`>;
|
|
26
|
+
/** Parses a standard real number (X.X) and returns a number
|
|
27
|
+
*/
|
|
28
|
+
export declare const realP: Parser<number>;
|
|
29
|
+
/** Parses an end of text/file. Fails if the parser is not at the end.
|
|
30
|
+
*/
|
|
31
|
+
export declare const eof: Parser<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { failure, success } from '../types';
|
|
2
|
+
import { map } from './map';
|
|
3
|
+
import { opt } from './opt';
|
|
4
|
+
import { regex } from './regex';
|
|
5
|
+
import { seq } from './seq';
|
|
6
|
+
import { str } from './str';
|
|
7
|
+
import { expect } from './utilities';
|
|
8
|
+
/** Parses 0 or more spaces
|
|
9
|
+
*/
|
|
10
|
+
export const spaces = regex(/ */, 'spaces');
|
|
11
|
+
/** Parses 1 or more spaces
|
|
12
|
+
*/
|
|
13
|
+
export const spacesPlus = regex(/ +/, 'spaces');
|
|
14
|
+
/** Parses 0 or more whitespace characters
|
|
15
|
+
*/
|
|
16
|
+
export const wspaces = opt(regex(/(?:\s|\t|\n|\r)+/, 'whitespace characters'));
|
|
17
|
+
/** Parses a boolean (true or false) and returns a string
|
|
18
|
+
*/
|
|
19
|
+
export const bool = regex(/true|false/, 'boolean');
|
|
20
|
+
/** Parses a boolean (true or false) and returns a boolean
|
|
21
|
+
*/
|
|
22
|
+
export const boolP = map(bool, val => val === 'true');
|
|
23
|
+
/** Parses an integer and returns a string
|
|
24
|
+
*/
|
|
25
|
+
export const int = regex(/\d+/, 'integer');
|
|
26
|
+
/** Parses an integer and returns a number
|
|
27
|
+
*/
|
|
28
|
+
export const intP = map(int, seq => parseInt(seq, 10));
|
|
29
|
+
/** Parses a standard real number (X.X) and returns a string
|
|
30
|
+
*/
|
|
31
|
+
export const real = expect(map(seq(int, str('.'), int), ([intPart, , decimalPart]) => `${intPart}.${decimalPart}`), 'real');
|
|
32
|
+
/** Parses a standard real number (X.X) and returns a number
|
|
33
|
+
*/
|
|
34
|
+
export const realP = map(real, (seq) => parseFloat(seq));
|
|
35
|
+
/** Parses an end of text/file. Fails if the parser is not at the end.
|
|
36
|
+
*/
|
|
37
|
+
export const eof = (ctx) => {
|
|
38
|
+
if (ctx.index === ctx.text.length) {
|
|
39
|
+
return success(ctx, void 0);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
return failure(ctx, "End Of File", ["EOF"]);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type Parser<T> = (ctx: Context) => Result<T>;
|
|
2
|
+
export type Context = Readonly<{
|
|
3
|
+
text: string;
|
|
4
|
+
path: string;
|
|
5
|
+
index: number;
|
|
6
|
+
}>;
|
|
7
|
+
export type Result<T> = Success<T> | Failure;
|
|
8
|
+
export type Success<T> = Readonly<{
|
|
9
|
+
success: true;
|
|
10
|
+
value: T;
|
|
11
|
+
ctx: Context;
|
|
12
|
+
}>;
|
|
13
|
+
export type Failure = Readonly<{
|
|
14
|
+
success: false;
|
|
15
|
+
expected: string;
|
|
16
|
+
ctx: Context;
|
|
17
|
+
history: string[];
|
|
18
|
+
}>;
|
|
19
|
+
export type TokenRange = {
|
|
20
|
+
start: number;
|
|
21
|
+
end: number;
|
|
22
|
+
};
|
|
23
|
+
export type Token<T> = TokenRange & {
|
|
24
|
+
value: T;
|
|
25
|
+
};
|
|
26
|
+
export declare function isFailure(input: unknown): input is Failure;
|
|
27
|
+
export declare function success<T>(ctx: Context, value: T): Success<T>;
|
|
28
|
+
export declare function failure(ctx: Context, expected: string, history: string[]): Failure;
|
|
29
|
+
export declare function result<T>(value: T): Parser<T>;
|
|
30
|
+
export declare function fail<T>(reason: string): Parser<T>;
|
|
31
|
+
export declare class ParseError extends Error {
|
|
32
|
+
readonly index: number;
|
|
33
|
+
readonly history: string[];
|
|
34
|
+
readonly line: string;
|
|
35
|
+
readonly column: number;
|
|
36
|
+
readonly row: number;
|
|
37
|
+
constructor(message: string, input: string, index: number, history: string[]);
|
|
38
|
+
private getInputData;
|
|
39
|
+
getPrettyErrorMessage(): string;
|
|
40
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function isFailure(input) {
|
|
2
|
+
return !input.success;
|
|
3
|
+
}
|
|
4
|
+
export function success(ctx, value) {
|
|
5
|
+
return { success: true, value, ctx };
|
|
6
|
+
}
|
|
7
|
+
export function failure(ctx, expected, history) {
|
|
8
|
+
return { success: false, expected, ctx, history };
|
|
9
|
+
}
|
|
10
|
+
export function result(value) {
|
|
11
|
+
return (ctx) => success(ctx, value);
|
|
12
|
+
}
|
|
13
|
+
export function fail(reason) {
|
|
14
|
+
return (ctx) => failure(ctx, reason, [reason]);
|
|
15
|
+
}
|
|
16
|
+
export class ParseError extends Error {
|
|
17
|
+
constructor(message, input, index, history) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.index = index;
|
|
20
|
+
this.history = history;
|
|
21
|
+
[this.line, this.column, this.row] = this.getInputData(input, index);
|
|
22
|
+
}
|
|
23
|
+
getInputData(input, index) {
|
|
24
|
+
const lines = input.split('\n');
|
|
25
|
+
let row = 0;
|
|
26
|
+
while (index > 0) {
|
|
27
|
+
if (lines[row].length > index) {
|
|
28
|
+
return [lines[row], index + 1, row + 1];
|
|
29
|
+
}
|
|
30
|
+
index -= lines[row].length + 1;
|
|
31
|
+
row += 1;
|
|
32
|
+
}
|
|
33
|
+
return [lines[row], index + 1, row + 1];
|
|
34
|
+
}
|
|
35
|
+
getPrettyErrorMessage() {
|
|
36
|
+
return `${this.message} (line ${this.row}, col ${this.column}):\n${this.line}\n${(this.column > 0 ? '-'.repeat(this.column - 1) : '') + '^'}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parser-combinators",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"maintainers": [
|
|
6
6
|
"Micha_i"
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
"homepage": "https://github.com/michalusio/Parser#readme",
|
|
16
16
|
"description": "A library of parser combinators, with which you can create your own parsers. The library will be continuously improved in time.",
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "tsc",
|
|
19
18
|
"start": "tsc && node .",
|
|
20
|
-
"lint": "eslint
|
|
19
|
+
"lint": "eslint src --ext .ts",
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"build-esm": "tsc --project tsconfig.esm.json",
|
|
22
|
+
"bundle": "npm run lint && npm run build && npm run build-esm",
|
|
21
23
|
"test:mutate": "stryker run",
|
|
22
24
|
"test:unit": "mocha",
|
|
23
25
|
"test": "nyc -e '.ts' --r html -r lcov -r text npm run test:unit"
|
|
@@ -25,6 +27,7 @@
|
|
|
25
27
|
"author": "Micha_i <isalski.michal@gmail.com> (https://github.com/michalusio)",
|
|
26
28
|
"main": "./dist/index.js",
|
|
27
29
|
"types": "./dist/index.d.ts",
|
|
30
|
+
"type": "commonjs",
|
|
28
31
|
"engines": {
|
|
29
32
|
"node": ">=18"
|
|
30
33
|
},
|
|
@@ -33,14 +36,15 @@
|
|
|
33
36
|
"@stryker-mutator/mocha-runner": "^9.4.0",
|
|
34
37
|
"@stryker-mutator/typescript-checker": "^9.4.0",
|
|
35
38
|
"@types/mocha": "10.0.10",
|
|
36
|
-
"@types/node": "25.0.
|
|
39
|
+
"@types/node": "25.0.9",
|
|
37
40
|
"cross-env": "10.1.0",
|
|
41
|
+
"esbuild": "0.27.2",
|
|
38
42
|
"eslint": "9.39.2",
|
|
39
43
|
"mocha": "11.7.5",
|
|
40
44
|
"nyc": "17.1.0",
|
|
41
45
|
"ts-node": "10.9.2",
|
|
42
46
|
"typescript": "5.9.3",
|
|
43
|
-
"typescript-eslint": "8.
|
|
47
|
+
"typescript-eslint": "8.53.0"
|
|
44
48
|
},
|
|
45
49
|
"keywords": [
|
|
46
50
|
"parser",
|