@borgar/fx 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/fx.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";const e="operator",t="context",n="range_beam",r="range_ternary",l="range_named",o="unknown",u="UnaryExpression",c="BinaryExpression",i="ReferenceIdentifier",s="CallExpression";function a(e){const t=/(?:\[(.+?)\])?([^[\]]+?)$/.exec(e);if(t){const[,e,n]=t;return{context:[e,n].filter(Boolean)}}}const f=e=>e&&":"===e.value&&{},p=e=>e&&"range"===e.type&&{r0:e.value},h=e=>e&&e.type===r&&{r0:e.value},g=e=>e&&"range"===e.type&&{r1:e.value},d=t=>t&&t.type===e&&"!"===t.value&&{},$=e=>e&&e.type===n&&{r0:e.value},y=e=>e&&"structured"===e.type&&{struct:e.value},x=e=>e&&e.type===t?a(e.value):e&&"context_quote"===e.type?a(e.value.slice(1,-1).replace(/''/g,"'")):void 0,v=e=>e&&e.type===l&&{name:e.value},m=[[h],[p,f,g],[p],[$],[x,d,h],[x,d,p,f,g],[x,d,p],[x,d,$]],E=m.concat([[v],[x,d,v],[y],[v,y],[x,d,v,y]]);function R(e,t){const n={withLocation:!1,mergeRefs:!1,allowTernary:!1,allowNamed:!0,r1c1:!1,...t},r=we(e,ge,n),l={context:[],r0:"",r1:"",name:""};r.length&&"fx_prefix"===r[0].type&&r.shift();const o=n.allowNamed?E:m;for(let e=0;e<o.length;e++){const t={...l};if(o[e].length===r.length){const n=o[e].every(((e,n)=>{const l=e(r[n]);return Object.assign(t,l),l}));if(n)return t}}return null}const w=/[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;function C(e){let t="",n=0,r=0;const l=e.context||[];for(let e=l.length;e>-1;e--){const o=l[e];if(o){t=(r%2?"["+o+"]":o)+t,n+=w.test(o),r++}}return n&&(t="'"+t.replace(/'/g,"''")+"'"),t?t+"!":t}const N=(e,t,n)=>Math.min(Math.max(t,e),n),A=(e,t)=>(t?"$":"")+I(e),b=(e,t)=>(t?"$":"")+String(e+1);function T(e){const t=e||"",n=t.length;let r=0;if(n>2){const e=t.charCodeAt(n-3);r+=676*(1+e-(e>95?32:0)-65)}if(n>1){const e=t.charCodeAt(n-2);r+=26*(1+e-(e>95?32:0)-65)}if(n){const e=t.charCodeAt(n-1);r+=e-(e>95?32:0)-65}return r}function I(e){return(e>=702?String.fromCharCode(((e-702)/676-0)%26+65):"")+(e>=26?String.fromCharCode(Math.floor((e/26-1)%26+65)):"")+String.fromCharCode(e%26+65)}function L(e){const t=/^(?=.)(\$(?=\D))?([A-Za-z]{0,3})?(\$)?([1-9][0-9]{0,6})?$/.exec(e);return t&&(t[2]||t[4])?[t[4]?(n=t[4],+n-1):null,t[2]?T(t[2]):null,!!t[3],!!t[1]]:null;var n}function O(e){let t=null,n=null,r=null,l=null,o=!1,u=!1,c=!1,i=!1;const[s,a,f]=e.split(":");if(f)return null;const p=L(s),h=a?L(a):null;if(!p||a&&!h)return null;if(null!=p[0]&&null!=p[1]?[t,n,o,u]=p:null==p[0]&&null!=p[1]?[,n,,u]=p:null!=p[0]&&null==p[1]&&([t,,o]=p),a)null!=h[0]&&null!=h[1]?[r,l,c,i]=h:null==h[0]&&null!=h[1]?[,l,,i]=h:null!=h[0]&&null==h[1]&&([r,,c]=h);else{if(null==t||null==n)return null;r=t,l=n,c=o,i=u}return null!=l&&(null==n||null!=n&&l<n)&&([n,l,u,i]=[l,n,i,u]),null!=r&&(null==t||null!=t&&r<t)&&([t,r,o,c]=[r,t,c,o]),{top:t,left:n,bottom:r,right:l,$top:o,$left:u,$bottom:c,$right:i}}function _(e){let{allowNamed:t=!0,allowTernary:n=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=R(e,{allowNamed:t,allowTernary:n,r1c1:!1});if(r&&(r.r0||r.name)){let e=null;return r.r0&&(e=O(r.r1?r.r0+":"+r.r1:r.r0)),r.name||e?(r.range=e,delete r.r0,delete r.r1,r):null}return null}function U(e){return C(e)+(e.name?e.name:function(e){let{top:t,left:n,bottom:r,right:l}=e;const{$left:o,$right:u,$top:c,$bottom:i}=e,s=null==n,a=null==l,f=null==t,p=null==r;return t=N(0,0|t,1048575),n=N(0,0|n,16383),!s&&!f&&a&&p?(r=t,l=n):(r=N(0,0|r,1048575),l=N(0,0|l,16383)),0===t&&r>=1048575||f&&p?A(n,o)+":"+A(l,u):0===n&&l>=16383||s&&a?b(t,c)+":"+b(r,i):s||f||a||!p?s||!f||a||p?s||f||!a||p?!s||f||a||p?l!==n||r!==t||u!==o||i!==c?A(n,o)+b(t,c)+":"+A(l,u)+b(r,i):A(n,o)+b(t,c):A(l,u)+b(t,c)+":"+b(r,i):A(n,o)+b(t,c)+":"+b(r,i):A(n,o)+b(r,i)+":"+A(l,u):A(n,o)+b(t,c)+":"+A(l,u)}(e.range))}function F(e){return null==e.top&&(e.top=0,e.$top=!1),null==e.bottom&&(e.bottom=1048575,e.$bottom=!1),null==e.left&&(e.left=0,e.$left=!1),null==e.right&&(e.right=16383,e.$right=!1),e}const S=/^\[('['#@[\]]|[^'#@[\]])+\]/i,M=/^([^#@[\]:]+)/i,k={headers:1,data:2,totals:4,all:8,"this row":16,"@":16},D=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return Object.freeze(t)},j={0:D(),1:D("headers"),2:D("data"),4:D("totals"),8:D("all"),16:D("this row"),3:D("headers","data"),6:D("data","totals")},z=function(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=S.exec(e);if(n){const e=n[0].slice(1,-1).replace(/'(['#@[\]])/g,"$1");return[n[0],e]}return t&&(n=M.exec(e),n)?[n[0],n[0]]:null};function W(e){const t=[];let n,r,l=0,o=e,u=0;if(!(n=/^(\[\s*)/.exec(o)))return null;if(r=/^\[#([a-z ]+)\]/i.exec(o)){const e=r[1].toLowerCase();if(l+=r[0].length,!k[e])return null;u|=k[e]}else if(r=z(o,!1))l+=r[0].length,t.push(r[1].trim());else{let r=!0;for(o=o.slice(n[1].length),l+=n[1].length;r&&(n=/^\[#([a-z ]+)\](\s*,\s*)?/i.exec(o));){const e=n[1].toLowerCase();if(!k[e])return null;u|=k[e],o=o.slice(n[0].length),l+=n[0].length,r=!!n[2]}if(r&&(n=/^@/.exec(o))&&(u|=k["@"],o=o.slice(1),l+=1,r="]"!==o[0]),!(u in j))return null;const c=r?z(e.slice(l)):null;if(c){if(l+=c[0].length,t.push(c[1].trim()),o=e.slice(l),":"===o[0]){o=o.slice(1),l++;const e=z(o);if(!e)return null;l+=e[0].length,t.push(e[1].trim())}r=!1}for(;" "===e[l];)l++;if(r||"]"!==e[l])return null;l++}const c=j[u];return{columns:t,sections:c?c.concat():c,length:l,token:e.slice(0,l)}}function q(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=R(e,t);if(n&&n.struct){const e=W(n.struct);if(e&&e.length===n.struct.length)return{context:n.context,table:n.name,columns:e.columns,sections:e.sections}}return null}function B(e){return e.replace(/([[\]#'@])/g,"'$1")}function Z(e){return e[0].toUpperCase()+e.slice(1).toLowerCase()}function P(e){let t=C(e);e.table&&(t+=e.table);const n=e.columns?.length??0,r=e.sections?.length??0;if(1!==r||n)if(r||1!==n){t+="[";const o=1===r&&"this row"===e.sections[0].toLowerCase();o?t+="@":r&&(t+=e.sections.map((e=>`[#${Z(e)}]`)).join(","),n&&(t+=",")),o&&1===e.columns.length&&(l=e.columns[0],/^[a-zA-Z0-9\u00a1-\uffff]+$/.test(l))?t+=B(e.columns[0]):n&&(t+=e.columns.slice(0,2).map((e=>`[${B(e)}]`)).join(":")),t+="]"}else t+=`[${B(e.columns[0])}]`;else t+=`[#${Z(e.sections[0])}]`;var l;return t}const X=/^(\[(?:[^\]])+\])?([0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]+)(?=!)/,H=/^'(?:''|[^'])*('|$)(?=!)/,Y="\\$?[A-Z]{1,3}\\$?[1-9][0-9]{0,6}",G="\\$?[A-Z]{1,3}",K="\\$?[1-9][0-9]{0,6}",V=new RegExp(`^${G}:${G}`,"i"),Q=new RegExp(`^${K}:${K}`,"i"),J=new RegExp(`^${Y}`,"i"),ee=new RegExp(`^((${G}|${K}):${Y}|${Y}:(${G}|${K}))(?![\\w($.])`,"i"),te="(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)",ne="(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)",re=new RegExp(`^${ne}(:${ne})?(?=\\W|$)`,"i"),le=new RegExp(`^${te}(:${te})?(?=\\W|$)`,"i"),oe=new RegExp(`^(?:(?=[RC])${te}${ne})`,"i"),ue=new RegExp(`^(${te}${ne}(:${ne}|:${te})(?![[\\d])|(${te}|${ne})(:${te}${ne}))(?=\\W|$)`,"i"),ce=/^(?![CR]\b)[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;function ie(e,t){return n=>{const r=t.exec(n);if(r)return{type:e,value:r[0]}}}function se(e){const t=W(e);if(t){let n=t.length;for(;" "===e[n];)n++;if("!"!==e[n])return{type:"structured",value:t.token}}return null}const ae=/([RC])(\[?)(-?\d+)/gi,fe=/(\d+|[a-zA-Z]+)/gi;function pe(e,t){let l,o;if(t.r1c1){if(t.allowTernary&&(l=ue.exec(e))?o={type:r,value:l[0]}:(l=oe.exec(e))?o={type:"range",value:l[0]}:((l=le.exec(e))||(l=re.exec(e)))&&(o={type:n,value:l[0]}),o){for(ae.lastIndex=0;null!==(l=ae.exec(o.value));){const e=("R"===l[1]?1048575:16383)+(l[2]?1:0),t=parseInt(l[3],10);if(t>=e||t<=-e)return null}return o}}else if(t.allowTernary&&(l=ee.exec(e))?o={type:r,value:l[0]}:(l=V.exec(e))||(l=Q.exec(e))?o={type:n,value:l[0]}:(l=J.exec(e))&&(o={type:"range",value:l[0]}),o){for(fe.lastIndex=0;null!==(l=fe.exec(o.value));)if(/^\d/.test(l[1])){if(parseInt(l[1],10)-1>1048575)return null}else if(T(l[1])>16383)return null;return o}}const he=[ie("error",/^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!|CONNECT!|BLOCKED!|EXTERNAL!)/i),ie(e,/^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/),ie("func",/^[A-Z_]+[A-Z\d_.]*(?=\()/i),ie("bool",/^(TRUE|FALSE)\b/i),ie("newline",/^\n+/),ie("whitespace",/^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/),ie("string",/^"(?:""|[^"])*("|$)/),ie("context_quote",H),ie(t,X),pe,se,ie("number",/^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/),ie(l,ce)],ge=[function(t,n){return n.r1c1?"!"===t[0]?{type:e,value:t[0]}:null:"!"===t[0]||":"===t[0]?{type:e,value:t[0]}:null},ie("context_quote",H),ie(t,X),pe,se,ie(l,ce)],de={};function $e(e,t){if(e.length){const n=e[0];t[n]=t[n]||{},$e(e.slice(1),t[n])}else t.$=!0}[["range",":","range"],["range"],[n],[r],[t,"!","range",":","range"],[t,"!","range"],[t,"!",n],[t,"!",r],["context_quote","!","range",":","range"],["context_quote","!","range"],["context_quote","!",n],["context_quote","!",r],[l],[t,"!",l],["context_quote","!",l],["structured"],[l,"structured"],[t,"!",l,"structured"],["context_quote","!",l,"structured"]].forEach((e=>$e(e.concat().reverse(),de)));const ye=function(t,n,r){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;const o=t[r-l];if(o){const u=o.type===e?o.value:o.type;if(u in n)return ye(t,n[u],r,l+1)}return n.$?l:0};function xe(e){const t=[];for(let n=e.length-1;n>=0;n--){let r=e[n];const l=ye(e,de,n);if(l){const t=e.slice(n-l+1,n+1);r={...r},r.value=t.map((e=>e.value)).join(""),r.loc&&t[0].loc&&(r.loc[0]=t[0].loc[0]),n-=l-1}t.unshift(r)}return t}const ve=(e,t)=>e&&e.type===t,me={withLocation:!1,mergeRefs:!0,allowTernary:!1,negativeNumbers:!0,r1c1:!1},Ee=e=>e.type===l||"func"===e.type,Re=t=>!ve(t,e)||"%"===t.value||"}"===t.value||")"===t.value||"#"===t.value;function we(t,n){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const l=Object.assign({},me,r),{withLocation:u,mergeRefs:c,negativeNumbers:i}=l,s=[];let a=0,f=null,p=null,h=null;const g=e=>{const t=e.type===o,n=h&&h.type===o;h&&(t&&n||t&&Ee(h)||n&&Ee(e))?(h.value+=e.value,h.type=o,u&&(h.loc[1]=e.loc[1])):(s.push(e),h=e,"whitespace"!==e.type&&"newline"!==e.type&&(p=f,f=e))};if(/^=/.test(t)){a++,g({type:"fx_prefix",value:"=",...u?{loc:[0,1]}:{}})}for(;a<t.length;){const r=a,c=t.slice(a);let d="",$="";for(let e=0;e<n.length;e++){const t=n[e](c,l);if(t){d=t.type,$=t.value,a+=$.length;break}}d||(d=o,$=t[a],a++);const y={type:d,value:$,...u?{loc:[r,a]}:{}};if("string"===d){const e=$.length;if('""'===$);else if('"'===$||'"'!==$[e-1])y.unterminated=!0;else if('""'!==$&&'"'===$[e-2]){let t=e-1;for(;'"'===$[t];)t--;!(t+1)^(e-t+1)%2==0&&(y.unterminated=!0)}}if(i&&"number"===d){const t=h;if(t&&ve(t,e)&&"-"===t.value&&(!p||ve(p,"fx_prefix")||!Re(p))){const e=s.pop();y.value="-"+$,u&&(y.loc[0]=e.loc[0]),f=p,h=s[s.length-1]}}g(y)}return c?xe(s):s}function Ce(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return we(e,he,t)}function Ne(e){return!!e&&("range"===e.type||e.type===n||e.type===r)}function Ae(e){return!!e&&("range"===e.type||e.type===n||e.type===r||"structured"===e.type||e.type===l)}function be(e){return!!e&&("bool"===e.type||"error"===e.type||"number"===e.type||"string"===e.type)}function Te(e){return!!e&&"error"===e.type}function Ie(e){return!!e&&("whitespace"===e.type||"newline"===e.type)}function Le(e){return!!e&&"func"===e.type}function Oe(e){return!!e&&"fx_prefix"===e.type}function _e(t){return!!t&&t.type===e}const Ue="(END)",Fe=["ANCHORARRAY","CHOOSE","DROP","IF","IFS","INDEX","INDIRECT","LAMBDA","LET","OFFSET","REDUCE","SINGLE","SWITCH","TAKE","XLOOKUP"],Se=e=>e.type===i||"ErrorLiteral"===e.type&&"#REF!"===e.value||e.type===c&&(":"===e.operator||" "===e.operator||","===e.operator)||e.type===s&&Fe.includes(e.callee.name.toUpperCase()),Me={};let ke,De,je,ze=!1;function We(e){const t=new SyntaxError(e);throw t.source=De.map((e=>e.value)).join(""),t}function qe(){let e,t=je;do{e=De[++t]}while(e&&(Ie(e)||_e(e)&&"("===e.value));return(e=>{const t=(e&&e.value)+"";return!(!Ae(e)&&(!_e(e)||":"!==t&&","!==t&&t.trim())&&(!Le(e)||!Fe.includes(t.toUpperCase()))&&(!Te(e)||"#REF!"!==t))})(e)}function Be(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if(e&&e!==ke.id&&We(`Expected ${e} but got ${ke.id}`),Ie(De[je])&&!qe())for(;Ie(De[je]);)je++;if(je>=De.length)return void(ke=Me[Ue]);const t=De[je];let n;je+=1,t.unterminated&&We("Encountered an unterminated token");let r=t.type;return _e(t)?(n=Me[t.value],n||We(`Unknown operator ${t.value}`)):Ie(t)?n=Me["(WHITESPACE)"]:be(t)?n=Me.Literal:Ae(t)?(n=Me[i],r=i):Le(t)?n=Me["(FUNCTION)"]:We(`Unexpected ${t.type} token: ${t.value}`),ke=Object.create(n),ke.type=r,ke.value=t.value,t.loc&&(ke.loc=[...t.loc]),ke}function Ze(e){let t,n=ke;for(Be(),t=n.nud();e<ke.lbp;)n=ke,Be(),t=n.led(t);return t}const Pe={nud:()=>We("Undefined"),led:()=>We("Missing operator")};function Xe(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=Me[e];return n?t>=n.lbp&&(n.lbp=t):(n={...Pe},n.id=e,n.value=e,n.lbp=t,Me[e]=n),n}function He(e,t,n){const r=Xe(e,t);return r.led=n||function(e){this.type=c,this.operator=this.value,delete this.value;const n=Ze(t);return this.arguments=[e,n],this.loc&&(this.loc=[e.loc[0],n.loc[1]]),this},r}function Ye(e,t){const n=Xe(e,0);return n.lbp=70,n.led=t||function(e){return this.type=u,this.operator=this.value,delete this.value,this.arguments=[e],this.loc&&(this.loc[0]=e.loc[0]),this},n}function Ge(e,t){const n=Xe(e);return n.nud=t||function(){this.type=u,this.operator=this.value,delete this.value;const e=Ze(70);return this.arguments=[e],this.loc&&(this.loc[1]=e.loc[1]),this},n}function Ke(e,t){return He(e,t,(function(n){Se(n)||We(`Unexpected ${e} operator`);const r=Ze(t);return Se(r)||We(`Unexpected ${ke.type} following ${this.id}`),this.type=c,this.operator=this.value.trim()?this.value:" ",delete this.value,this.arguments=[n,r],this.loc&&(this.loc=[n.loc[0],r.loc[1]]),this}))}Xe(Ue),Ke(":",80);const Ve=Ke(",",80);Ke("(WHITESPACE)",80);const Qe=e=>{const t=Ve.lbp>0;return null!=e&&(Ve.lbp=e?80:0),t};function Je(){let e=1;return()=>"fxg"+e++}function et(e,t){return null==e&&null==t||e===t}function tt(e,t){return!e&&!t||String(e).toLowerCase()===String(t).toLowerCase()}function nt(e,t){return(!e.name&&!t.name||e.name===t.name)&&(!!(!e.range&&!t.range||et(e.range.top,t.range.top)&&et(e.range.bottom,t.range.bottom)&&et(e.range.left,t.range.left)&&et(e.range.right,t.range.right))&&!(!tt(e.context[0],t.context[0])||!tt(e.context[1],t.context[1])))}Ye("%"),Ye("#",(function(e){return Se(e)||We("# expects a reference"),this.type=u,this.operator=this.value,delete this.value,this.arguments=[e],this})),Ge("+"),Ge("-"),Ge("@"),He("^",50),He("*",40),He("/",40),He("+",30),He("-",30),He("&",20),He("=",10),He("<",10),He(">",10),He("<=",10),He(">=",10),He("<>",10),Xe("Literal").nud=function(){const{type:e,value:t}=this;if(this.type="Literal",this.raw=t,"number"===e)this.value=+t;else if("bool"===e)this.value="TRUE"===t.toUpperCase();else if("error"===e)this.type="ErrorLiteral",this.value=t.toUpperCase();else{if("string"!==e)throw new Error("Unsupported literal type: "+e);this.value=t.slice(1,-1).replace(/""/g,'"')}return this},Xe(i).nud=function(){return this.type=i,this},Xe(")"),Ge("(",(function(){const e=Qe(!0),t=Ze(0);return Be(")"),Qe(e),t})),Xe("(FUNCTION)").nud=function(){return this},He("(",90,(function(e){"(FUNCTION)"!==e.id&&We("Cannot call a "+e.type);const t=[];let n=!1;if(")"!==ke.id){const e=Qe(!1);for(;")"!==ke.id;)if(","===ke.id)t.push(null),n=!0,Be();else{const e=Ze(0);t.push(e),n=!1,","===ke.id&&(Be(","),n=!0)}Qe(e)}n&&t.push(null);const r=ke;return Be(")"),delete this.value,this.type=s,this.callee={type:"Identifier",name:e.value},e.loc&&(this.callee.loc=[...e.loc]),this.arguments=t,e.loc&&(this.loc=[e.loc[0],r.loc[1]]),this})),Xe("}"),Xe(";"),Ge("{",(function(){"}"===ke.id&&We("Unexpected empty array");let e=[],t=!1;const n=[e],r=Qe(!1);for(;!t;)be(ke)?e.push(Me.Literal.nud.call(ke)):ze&&Se(ke)?e.push(Me[i].nud.call(ke)):We(`Unexpected ${ke.type} in array: ${ke.value}`),Be(),","===ke.id?Be(","):";"===ke.id?(Be(";"),e=[],n.push(e)):t=!0;const l=ke;return Be("}"),Qe(r),this.type="ArrayExpression",this.elements=n,this.loc&&(this.loc[1]=l.loc[1]),delete this.value,this}));const rt=(e,t,n)=>Math.min(Math.max(t,e),n);function lt(e,t){return t?String(e+1):e?"["+e+"]":""}function ot(e){let t=null,n=null,r=null,l=null;const o=/^R(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);o&&(o[1]?(t=parseInt(o[1],10),r=!1):o[2]?(t=parseInt(o[2],10)-1,r=!0):(t=0,r=!1),e=e.slice(o[0].length));const u=/^C(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);return u&&(u[1]?(n=parseInt(u[1],10),l=!1):u[2]?(n=parseInt(u[2],10)-1,l=!0):(n=0,l=!1),e=e.slice(u[0].length)),!o&&!u||e.length?null:[t,n,r,l]}function ut(e){let t=null;const[n,r]=e.split(":",2),l=ot(n);if(l){const[e,n,o,u]=l;if(!r)return null!=e&&null==n?{r0:e,c0:null,r1:e,c1:null,$r0:o,$c0:!1,$r1:o,$c1:!1}:null==e&&null!=n?{r0:null,c0:n,r1:null,c1:n,$r0:!1,$c0:u,$r1:!1,$c1:u}:{r0:e||0,c0:n||0,r1:e||0,c1:n||0,$r0:o||!1,$c0:u||!1,$r1:o||!1,$c1:u||!1};{const l=ot(r);if(!l)return null;{t={};const[r,c,i,s]=l;null!=e&&null!=r?(t.r0=o===i?Math.min(e,r):e,t.$r0=o,t.r1=o===i?Math.max(e,r):r,t.$r1=i):null!=e&&null==r?(t.r0=e,t.$r0=o,t.r1=null,t.$r1=o):null==e&&null!=r?(t.r0=r,t.$r0=i,t.r1=null,t.$r1=i):null==e&&null==r&&(t.r0=null,t.$r0=!1,t.r1=null,t.$r1=!1),null!=n&&null!=c?(t.c0=u===s?Math.min(n,c):n,t.$c0=u,t.c1=u===s?Math.max(n,c):c,t.$c1=s):null!=n&&null==c?(t.c0=n,t.$c0=u,t.c1=null,t.$c1=u):null==n&&null!=c?(t.c0=c,t.$c0=s,t.c1=null,t.$c1=s):null==n&&null==c&&(t.c0=null,t.$c0=!1,t.c1=null,t.$c1=!1)}}}return t}function ct(e){let{allowNamed:t=!0,allowTernary:n=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=R(e,{allowNamed:t,allowTernary:n,r1c1:!0});if(r&&(r.r0||r.name)){const e=r.r1?ut(r.r0+":"+r.r1):ut(r.r0);return r.name||e?(r.range=e,delete r.r0,delete r.r1,r):null}return null}function it(e){return C(e)+(e.name?e.name:function(e){let{r0:t,c0:n,r1:r,c1:l}=e;const{$c0:o,$c1:u,$r0:c,$r1:i}=e,s=null==t,a=null==n;let f=null==r,p=null==l;if(t=rt(c?0:-1048575,0|t,1048575),n=rt(o?0:-16383,0|n,16383),!s&&f&&!a&&p?(r=t,f=!1,l=n,p=!1):(r=rt(i?0:-1048575,0|r,1048575),l=rt(u?0:-16383,0|l,16383)),0===t&&r>=1048575||s&&f){const e=lt(n,o),t=lt(l,u);return"C"+(e===t?e:e+":C"+t)}if(0===n&&l>=16383||a&&p){const e=lt(t,c),n=lt(r,i);return"R"+(e===n?e:e+":R"+n)}const h=lt(t,c),g=lt(r,i),d=lt(n,o),$=lt(l,u);return s||f||a||p?(s?"":"R"+h)+(a?"":"C"+d)+":"+(f?"":"R"+g)+(p?"":"C"+$):h!==g||d!==$?"R"+h+"C"+d+":R"+g+"C"+$:"R"+h+"C"+d}(e.range))}const st=(e,t,n)=>null==t?null:e?t:t-n,at={withLocation:!1,mergeRefs:!1,allowTernary:!0,r1c1:!1};function ft(e,t,n,r){let l=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=e;if(null!=o&&!t){if(o=n+e,o<0){if(!l)return NaN;o=r+o+1}if(o>r){if(!l)return NaN;o-=r+1}}return o}const pt={wrapEdges:!0,mergeRefs:!0};const ht=Object.freeze({OPERATOR:e,BOOLEAN:"bool",ERROR:"error",NUMBER:"number",FUNCTION:"func",NEWLINE:"newline",WHITESPACE:"whitespace",STRING:"string",CONTEXT:t,CONTEXT_QUOTE:"context_quote",REF_RANGE:"range",REF_BEAM:n,REF_TERNARY:r,REF_NAMED:l,REF_STRUCT:"structured",FX_PREFIX:"fx_prefix",UNKNOWN:o}),gt=Object.freeze({UNARY:u,BINARY:c,REFERENCE:i,LITERAL:"Literal",ERROR:"ErrorLiteral",CALL:s,ARRAY:"ArrayExpression",IDENTIFIER:"Identifier"});exports.MAX_COLS=16383,exports.MAX_ROWS=1048575,exports.addA1RangeBounds=F,exports.addTokenMeta=function(e){let{sheetName:t="",workbookName:l=""}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const u=[];let c=null;const i=Je(),s=[],a=()=>u.length+(c?1:0);return e.forEach(((e,f)=>{if(e.index=f,e.depth=a(),"("===e.value)u.push(e),e.depth=a();else if(")"===e.value){const t=u.pop();if(t){const n=i();e.groupId=n,e.depth=t.depth,t.groupId=n}else e.error=!0}else if("{"===e.value)c?e.error=!0:(c=e,e.depth=a());else if("}"===e.value){if(c){const t=i();e.groupId=t,e.depth=c.depth,c.groupId=t}else e.error=!0;c=null}else if("range"===e.type||e.type===n||e.type===r){const n=_(e.value,{allowTernary:!0});if(n&&n.range){if(n.source=e.value,n.context.length){if(1===n.context.length){const e=n.context[0];n.context=e===t||e===l?[l,t]:[l,e]}}else n.context=[l,t];const r=s.find((e=>nt(e,n)));r?e.groupId=r.groupId:(n.groupId=i(),e.groupId=n.groupId,s.push(n))}}else e.type===o&&(e.error=!0)})),e},exports.fixRanges=function e(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{addBounds:!1};if("string"==typeof t)return e(Ce(t,n),n).map((e=>e.value)).join("");if(!Array.isArray(t))throw new Error("fixRanges expects an array of tokens");const{addBounds:r,r1c1:l}=n;if(l)throw new Error("fixRanges does not have an R1C1 mode");let o=0;return t.map((e=>{const t={...e};e.loc&&(t.loc=[...e.loc]);let n=0;if("structured"===t.type){const e=P(q(t.value));n=e.length-t.value.length,t.value=e}else if(Ne(t)){const e=_(t.value,{allowTernary:!0}),l=e.range;r&&F(l);const o=U(e);n=o.length-t.value.length,t.value=o}return o||n?(t.loc&&(t.loc[0]+=o),o+=n,t.loc&&(t.loc[1]+=o)):o+=n,t}))},exports.fromCol=T,exports.isError=Te,exports.isFunction=Le,exports.isFxPrefix=Oe,exports.isLiteral=be,exports.isOperator=_e,exports.isRange=Ne,exports.isReference=Ae,exports.isWhitespace=Ie,exports.mergeRefTokens=xe,exports.nodeTypes=gt,exports.parse=function(e,t){if("string"==typeof e)De=Ce(e,{withLocation:!0,...t,mergeRefs:!0});else{if(!Array.isArray(e))throw new Error("Parse requires a string or array of tokens.");De=e}for(ze=t?.permitArrayRanges,je=0;Ie(De[je])||Oe(De[je]);)je++;Be(),Qe(!0);const n=Ze(0);return Be(Ue),n},exports.parseA1Ref=_,exports.parseR1C1Ref=ct,exports.parseStructRef=q,exports.stringifyA1Ref=U,exports.stringifyR1C1Ref=it,exports.stringifyStructRef=P,exports.toCol=I,exports.tokenTypes=ht,exports.tokenize=Ce,exports.translateToA1=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:pt;const r=O(t),l="string"==typeof e,o={...pt,...n},u=l?Ce(e,{withLocation:!1,mergeRefs:o.mergeRefs,allowTernary:!0,r1c1:!0}):e;let c=0;return u.forEach((e=>{if(Ne(e)){const t=e.value,n=ct(t,{allowTernary:!0}),l=n.range,u={},i=ft(l.r0,l.$r0,r.top,1048575,o.wrapEdges),s=ft(l.r1,l.$r1,r.top,1048575,o.wrapEdges);i>s?(u.top=s,u.$top=l.$r1,u.bottom=i,u.$bottom=l.$r0):(u.top=i,u.$top=l.$r0,u.bottom=s,u.$bottom=l.$r1);const a=ft(l.c0,l.$c0,r.left,16383,o.wrapEdges),f=ft(l.c1,l.$c1,r.left,16383,o.wrapEdges);a>f?(u.left=f,u.$left=l.$c1,u.right=a,u.$right=l.$c0):(u.left=a,u.$left=l.$c0,u.right=f,u.$right=l.$c1),isNaN(i)||isNaN(s)||isNaN(a)||isNaN(f)?(e.type="error",e.value="#REF!",delete e.groupId):(n.range=u,e.value=U(n)),e.loc&&(e.loc[0]+=c,c+=e.value.length-t.length,e.loc[1]+=c)}else c&&e.loc&&(e.loc[0]+=c,e.loc[1]+=c)})),l?u.map((e=>e.value)).join(""):u},exports.translateToR1C1=function(e,t){const{top:n,left:r}=O(t),l="string"==typeof e,o=l?Ce(e,at):e;let u=0;return o.forEach((e=>{if(Ne(e)){const t=e.value,l=_(t,{allowTernary:!0}),o=l.range,c={};c.r0=st(o.$top,o.top,n),c.r1=st(o.$bottom,o.bottom,n),c.c0=st(o.$left,o.left,r),c.c1=st(o.$right,o.right,r),c.$r0=o.$top,c.$r1=o.$bottom,c.$c0=o.$left,c.$c1=o.$right,l.range=c,e.value=it(l),e.loc&&(e.loc[0]+=u,u+=e.value.length-t.length,e.loc[1]+=u)}else u&&e.loc&&(e.loc[0]+=u,e.loc[1]+=u)})),l?o.map((e=>e.value)).join(""):o};
1
+ "use strict";const e="operator",t="error",n="context",l="range_beam",r="range_ternary",o="range_named",u="structured",i="unknown",c="UnaryExpression",s="BinaryExpression",a="ReferenceIdentifier",f="CallExpression";function p(e){const t=/(?:\[(.+?)\])?([^[\]]+?)$/.exec(e);if(t){const[,e,n]=t;return{context:[e,n].filter(Boolean)}}}const h=e=>e&&":"===e.value&&{},g=e=>e&&"range"===e.type&&{r0:e.value},d=e=>e&&e.type===r&&{r0:e.value},$=e=>e&&"range"===e.type&&{r1:e.value},y=t=>t&&t.type===e&&"!"===t.value&&{},x=e=>e&&e.type===l&&{r0:e.value},v=e=>e&&e.type===u&&{struct:e.value},m=e=>e&&e.type===n?p(e.value):e&&"context_quote"===e.type?p(e.value.slice(1,-1).replace(/''/g,"'")):void 0,E=e=>e&&e.type===o&&{name:e.value},R=[[d],[g,h,$],[g],[x],[m,y,d],[m,y,g,h,$],[m,y,g],[m,y,x]],w=R.concat([[E],[m,y,E],[v],[E,v],[m,y,E,v]]);function C(e,t){const n={withLocation:!1,mergeRefs:!1,allowTernary:!1,allowNamed:!0,r1c1:!1,...t},l=Ae(e,$e,n),r={context:[],r0:"",r1:"",name:""};l.length&&"fx_prefix"===l[0].type&&l.shift();const o=n.allowNamed?w:R;for(let e=0;e<o.length;e++){const t={...r};if(o[e].length===l.length){const n=o[e].every(((e,n)=>{const r=e(l[n]);return Object.assign(t,r),r}));if(n)return t}}return null}const A=/[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;function N(e){let t="",n=0,l=0;const r=e.context||[];for(let e=r.length;e>-1;e--){const o=r[e];if(o){t=(l%2?"["+o+"]":o)+t,n+=A.test(o),l++}}return n&&(t="'"+t.replace(/'/g,"''")+"'"),t?t+"!":t}const b=(e,t,n)=>Math.min(Math.max(t,e),n),T=(e,t)=>(t?"$":"")+O(e),I=(e,t)=>(t?"$":"")+String(e+1);function L(e){const t=e||"",n=t.length;let l=0;if(n>2){const e=t.charCodeAt(n-3);l+=676*(1+e-(e>95?32:0)-65)}if(n>1){const e=t.charCodeAt(n-2);l+=26*(1+e-(e>95?32:0)-65)}if(n){const e=t.charCodeAt(n-1);l+=e-(e>95?32:0)-65}return l}function O(e){return(e>=702?String.fromCharCode(((e-702)/676-0)%26+65):"")+(e>=26?String.fromCharCode(Math.floor((e/26-1)%26+65)):"")+String.fromCharCode(e%26+65)}function _(e){const t=/^(?=.)(\$(?=\D))?([A-Za-z]{0,3})?(\$)?([1-9][0-9]{0,6})?$/.exec(e);return t&&(t[2]||t[4])?[t[4]?(n=t[4],+n-1):null,t[2]?L(t[2]):null,!!t[3],!!t[1]]:null;var n}function U(e){let t=null,n=null,l=null,r=null,o=!1,u=!1,i=!1,c=!1;const[s,a,f]=e.split(":");if(f)return null;const p=_(s),h=a?_(a):null;if(!p||a&&!h)return null;if(null!=p[0]&&null!=p[1]?[t,n,o,u]=p:null==p[0]&&null!=p[1]?[,n,,u]=p:null!=p[0]&&null==p[1]&&([t,,o]=p),a)null!=h[0]&&null!=h[1]?[l,r,i,c]=h:null==h[0]&&null!=h[1]?[,r,,c]=h:null!=h[0]&&null==h[1]&&([l,,i]=h);else{if(null==t||null==n)return null;l=t,r=n,i=o,c=u}return null!=r&&(null==n||null!=n&&r<n)&&([n,r,u,c]=[r,n,c,u]),null!=l&&(null==t||null!=t&&l<t)&&([t,l,o,i]=[l,t,i,o]),{top:t,left:n,bottom:l,right:r,$top:o,$left:u,$bottom:i,$right:c}}function F(e){let{allowNamed:t=!0,allowTernary:n=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const l=C(e,{allowNamed:t,allowTernary:n,r1c1:!1});if(l&&(l.r0||l.name)){let e=null;return l.r0&&(e=U(l.r1?l.r0+":"+l.r1:l.r0)),l.name||e?(l.range=e,delete l.r0,delete l.r1,l):null}return null}function S(e){return N(e)+(e.name?e.name:function(e){let{top:t,left:n,bottom:l,right:r}=e;const{$left:o,$right:u,$top:i,$bottom:c}=e,s=null==n,a=null==r,f=null==t,p=null==l;return t=b(0,0|t,1048575),n=b(0,0|n,16383),!s&&!f&&a&&p?(l=t,r=n):(l=b(0,0|l,1048575),r=b(0,0|r,16383)),0===t&&l>=1048575||f&&p?T(n,o)+":"+T(r,u):0===n&&r>=16383||s&&a?I(t,i)+":"+I(l,c):s||f||a||!p?s||!f||a||p?s||f||!a||p?!s||f||a||p?r!==n||l!==t||u!==o||c!==i?T(n,o)+I(t,i)+":"+T(r,u)+I(l,c):T(n,o)+I(t,i):T(r,u)+I(t,i)+":"+I(l,c):T(n,o)+I(t,i)+":"+I(l,c):T(n,o)+I(l,c)+":"+T(r,u):T(n,o)+I(t,i)+":"+T(r,u)}(e.range))}function M(e){return null==e.top&&(e.top=0,e.$top=!1),null==e.bottom&&(e.bottom=1048575,e.$bottom=!1),null==e.left&&(e.left=0,e.$left=!1),null==e.right&&(e.right=16383,e.$right=!1),e}const k=/^\[('['#@[\]]|[^'#@[\]])+\]/i,D=/^([^#@[\]:]+)/i,j={headers:1,data:2,totals:4,all:8,"this row":16,"@":16},z=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return Object.freeze(t)},W={0:z(),1:z("headers"),2:z("data"),4:z("totals"),8:z("all"),16:z("this row"),3:z("headers","data"),6:z("data","totals")},q=function(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=k.exec(e);if(n){const e=n[0].slice(1,-1).replace(/'(['#@[\]])/g,"$1");return[n[0],e]}return t&&(n=D.exec(e),n)?[n[0],n[0]]:null};function B(e){const t=[];let n,l,r=0,o=e,u=0;if(!(n=/^(\[\s*)/.exec(o)))return null;if(l=/^\[#([a-z ]+)\]/i.exec(o)){const e=l[1].toLowerCase();if(r+=l[0].length,!j[e])return null;u|=j[e]}else if(l=q(o,!1))r+=l[0].length,t.push(l[1].trim());else{let l=!0;for(o=o.slice(n[1].length),r+=n[1].length;l&&(n=/^\[#([a-z ]+)\](\s*,\s*)?/i.exec(o));){const e=n[1].toLowerCase();if(!j[e])return null;u|=j[e],o=o.slice(n[0].length),r+=n[0].length,l=!!n[2]}if(l&&(n=/^@/.exec(o))&&(u|=j["@"],o=o.slice(1),r+=1,l="]"!==o[0]),!(u in W))return null;const i=l?q(e.slice(r)):null;if(i){if(r+=i[0].length,t.push(i[1].trim()),o=e.slice(r),":"===o[0]){o=o.slice(1),r++;const e=q(o);if(!e)return null;r+=e[0].length,t.push(e[1].trim())}l=!1}for(;" "===e[r];)r++;if(l||"]"!==e[r])return null;r++}const i=W[u];return{columns:t,sections:i?i.concat():i,length:r,token:e.slice(0,r)}}function Z(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=C(e,t);if(n&&n.struct){const e=B(n.struct);if(e&&e.length===n.struct.length)return{context:n.context,table:n.name,columns:e.columns,sections:e.sections}}return null}function P(e){return e.replace(/([[\]#'@])/g,"'$1")}function X(e){return e[0].toUpperCase()+e.slice(1).toLowerCase()}function H(e){let t=N(e);e.table&&(t+=e.table);const n=e.columns?.length??0,l=e.sections?.length??0;if(1!==l||n)if(l||1!==n){t+="[";const o=1===l&&"this row"===e.sections[0].toLowerCase();o?t+="@":l&&(t+=e.sections.map((e=>`[#${X(e)}]`)).join(","),n&&(t+=",")),o&&1===e.columns.length&&(r=e.columns[0],/^[a-zA-Z0-9\u00a1-\uffff]+$/.test(r))?t+=P(e.columns[0]):n&&(t+=e.columns.slice(0,2).map((e=>`[${P(e)}]`)).join(":")),t+="]"}else t+=`[${P(e.columns[0])}]`;else t+=`[#${X(e.sections[0])}]`;var r;return t}const Y=/^(\[(?:[^\]])+\])?([0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]+)(?=!)/,G=/^'(?:''|[^'])*('|$)(?=!)/,K="\\$?[A-Z]{1,3}\\$?[1-9][0-9]{0,6}",V="\\$?[A-Z]{1,3}",Q="\\$?[1-9][0-9]{0,6}",J=new RegExp(`^${V}:${V}`,"i"),ee=new RegExp(`^${Q}:${Q}`,"i"),te=new RegExp(`^${K}`,"i"),ne=new RegExp(`^((${V}|${Q}):${K}|${K}:(${V}|${Q}))(?![\\w($.])`,"i"),le="(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)",re="(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)",oe=new RegExp(`^${re}(:${re})?(?=\\W|$)`,"i"),ue=new RegExp(`^${le}(:${le})?(?=\\W|$)`,"i"),ie=new RegExp(`^(?:(?=[RC])${le}${re})`,"i"),ce=new RegExp(`^(${le}${re}(:${re}|:${le})(?![[\\d])|(${le}|${re})(:${le}${re}))(?=\\W|$)`,"i"),se=/^(?![CR]\b)[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;function ae(e,t){return n=>{const l=t.exec(n);if(l)return{type:e,value:l[0]}}}function fe(e){const t=B(e);if(t){let n=t.length;for(;" "===e[n];)n++;if("!"!==e[n])return{type:u,value:t.token}}return null}const pe=/([RC])(\[?)(-?\d+)/gi,he=/(\d+|[a-zA-Z]+)/gi;function ge(e,t){let n,o;if(t.r1c1){if(t.allowTernary&&(n=ce.exec(e))?o={type:r,value:n[0]}:(n=ie.exec(e))?o={type:"range",value:n[0]}:((n=ue.exec(e))||(n=oe.exec(e)))&&(o={type:l,value:n[0]}),o){for(pe.lastIndex=0;null!==(n=pe.exec(o.value));){const e=("R"===n[1]?1048575:16383)+(n[2]?1:0),t=parseInt(n[3],10);if(t>=e||t<=-e)return null}return o}}else if(t.allowTernary&&(n=ne.exec(e))?o={type:r,value:n[0]}:(n=J.exec(e))||(n=ee.exec(e))?o={type:l,value:n[0]}:(n=te.exec(e))&&(o={type:"range",value:n[0]}),o){for(he.lastIndex=0;null!==(n=he.exec(o.value));)if(/^\d/.test(n[1])){if(parseInt(n[1],10)-1>1048575)return null}else if(L(n[1])>16383)return null;return o}}const de=[ae(t,/^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!|CONNECT!|BLOCKED!|EXTERNAL!)/i),ae(e,/^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/),ae("func",/^[A-Z_]+[A-Z\d_.]*(?=\()/i),ae("bool",/^(TRUE|FALSE)\b/i),ae("newline",/^\n+/),ae("whitespace",/^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/),ae("string",/^"(?:""|[^"])*("|$)/),ae("context_quote",G),ae(n,Y),ge,fe,ae("number",/^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/),ae(o,se)],$e=[function(t,n){return n.r1c1?"!"===t[0]?{type:e,value:t[0]}:null:"!"===t[0]||":"===t[0]?{type:e,value:t[0]}:null},ae("context_quote",G),ae(n,Y),ge,fe,ae(o,se)],ye={};function xe(e,t){if(e.length){const n=e[0];t[n]=t[n]||{},xe(e.slice(1),t[n])}else t.$=!0}[["range",":","range"],["range"],[l],[r],[n,"!","range",":","range"],[n,"!","range"],[n,"!",l],[n,"!",r],["context_quote","!","range",":","range"],["context_quote","!","range"],["context_quote","!",l],["context_quote","!",r],[o],[n,"!",o],["context_quote","!",o],[u],[o,u],[n,"!",o,u],["context_quote","!",o,u]].forEach((e=>xe(e.concat().reverse(),ye)));const ve=function(t,n,l){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;const o=t[l-r];if(o){const u=o.type===e?o.value:o.type;if(u in n)return ve(t,n[u],l,r+1)}return n.$?r:0};function me(e){const t=[];for(let n=e.length-1;n>=0;n--){let l=e[n];const r=ve(e,ye,n);if(r){const t=e.slice(n-r+1,n+1);l={...l},l.value=t.map((e=>e.value)).join(""),l.loc&&t[0].loc&&(l.loc[0]=t[0].loc[0]),n-=r-1}t.unshift(l)}return t}const Ee=(e,t)=>e&&e.type===t,Re={withLocation:!1,mergeRefs:!0,allowTernary:!1,negativeNumbers:!0,r1c1:!1},we=e=>e.type===o||"func"===e.type,Ce=t=>!Ee(t,e)||"%"===t.value||"}"===t.value||")"===t.value||"#"===t.value;function Ae(t,n){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const r=Object.assign({},Re,l),{withLocation:o,mergeRefs:u,negativeNumbers:c}=r,s=[];let a=0,f=null,p=null,h=null;const g=e=>{const t=e.type===i,n=h&&h.type===i;h&&(t&&n||t&&we(h)||n&&we(e))?(h.value+=e.value,h.type=i,o&&(h.loc[1]=e.loc[1])):(s.push(e),h=e,"whitespace"!==e.type&&"newline"!==e.type&&(p=f,f=e))};if(/^=/.test(t)){a++,g({type:"fx_prefix",value:"=",...o?{loc:[0,1]}:{}})}for(;a<t.length;){const l=a,u=t.slice(a);let d="",$="";for(let e=0;e<n.length;e++){const t=n[e](u,r);if(t){d=t.type,$=t.value,a+=$.length;break}}d||(d=i,$=t[a],a++);const y={type:d,value:$,...o?{loc:[l,a]}:{}};if("string"===d){const e=$.length;if('""'===$);else if('"'===$||'"'!==$[e-1])y.unterminated=!0;else if('""'!==$&&'"'===$[e-2]){let t=e-1;for(;'"'===$[t];)t--;!(t+1)^(e-t+1)%2==0&&(y.unterminated=!0)}}if(c&&"number"===d){const t=h;if(t&&Ee(t,e)&&"-"===t.value&&(!p||Ee(p,"fx_prefix")||!Ce(p))){const e=s.pop();y.value="-"+$,o&&(y.loc[0]=e.loc[0]),f=p,h=s[s.length-1]}}g(y)}return u?me(s):s}function Ne(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Ae(e,de,t)}function be(e){return!!e&&("range"===e.type||e.type===l||e.type===r)}function Te(e){return!!e&&("range"===e.type||e.type===l||e.type===r||e.type===u||e.type===o)}function Ie(e){return!!e&&("bool"===e.type||e.type===t||"number"===e.type||"string"===e.type)}function Le(e){return!!e&&e.type===t}function Oe(e){return!!e&&("whitespace"===e.type||"newline"===e.type)}function _e(e){return!!e&&"func"===e.type}function Ue(e){return!!e&&"fx_prefix"===e.type}function Fe(t){return!!t&&t.type===e}const Se="(END)",Me=["ANCHORARRAY","CHOOSE","DROP","IF","IFS","INDEX","INDIRECT","LAMBDA","LET","OFFSET","REDUCE","SINGLE","SWITCH","TAKE","XLOOKUP"],ke=e=>!!e&&(e.type===a||("ErrorLiteral"===e.type||e.type===t)&&"#REF!"===e.value||e.type===s&&(":"===e.operator||" "===e.operator||","===e.operator)||e.type===f&&Me.includes(e.callee.name.toUpperCase())),De={};let je,ze,We,qe=!1,Be=!1;function Ze(e){const t=new Error(e);throw t.source=ze.map((e=>e.value)).join(""),t.sourceOffset=ze.slice(0,We).reduce(((e,t)=>e+t.value),"").length,t}function Pe(){let e,t=We;do{e=ze[++t]}while(e&&(Oe(e)||Fe(e)&&"("===e.value));return(e=>{const t=(e&&e.value)+"";return!(!Te(e)&&(!Fe(e)||":"!==t&&","!==t&&t.trim())&&(!_e(e)||!Me.includes(t.toUpperCase()))&&(!Le(e)||"#REF!"!==t))})(e)}function Xe(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(e&&e!==je.id&&Ze(`Expected ${e} but got ${je.id}`),Oe(ze[We])){if(!(ke(t)&&Pe()))for(;Oe(ze[We]);)We++}if(We>=ze.length)return void(je=De[Se]);const n=ze[We];let l;We+=1,n.unterminated&&Ze("Encountered an unterminated token");let r=n.type;return Fe(n)?(l=De[n.value],l||Ze(`Unknown operator ${n.value}`)):Oe(n)?l=De["(WHITESPACE)"]:Ie(n)?l=De.Literal:Te(n)?(l=De[a],r=a):_e(n)?l=De["(FUNCTION)"]:Ze(`Unexpected ${n.type} token: ${n.value}`),je=Object.create(l),je.type=r,je.value=n.value,n.loc&&(je.loc=[...n.loc]),je}function He(e){let t=je;Xe(null,t);let n=t.nud();for(;e<je.lbp;)t=je,Xe(null,t),n=t.led(n);return n}const Ye={nud:()=>Ze("Invalid syntax"),led:()=>Ze("Missing operator")};function Ge(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=De[e];return n?t>=n.lbp&&(n.lbp=t):(n={...Ye},n.id=e,n.value=e,n.lbp=t,De[e]=n),n}function Ke(e,t,n){const l=Ge(e,t);return l.led=n||function(e){this.type=s,this.operator=this.value,delete this.value;const n=He(t);return this.arguments=[e,n],this.loc&&(this.loc=[e.loc[0],n.loc[1]]),this},l}function Ve(e,t){const n=Ge(e,0);return n.lbp=70,n.led=t||function(e){return this.type=c,this.operator=this.value,delete this.value,this.arguments=[e],this.loc&&(this.loc[0]=e.loc[0]),this},n}function Qe(e,t){const n=Ge(e);return n.nud=t||function(){this.type=c,this.operator=this.value,delete this.value;const e=He(70);return this.arguments=[e],this.loc&&(this.loc[1]=e.loc[1]),this},n}function Je(e,t){return Ke(e,t,(function(n){ke(n)||Ze(`Unexpected ${e} operator`);const l=He(t);return ke(l)||Ze(`Unexpected ${je.type} following ${this.id}`),this.type=s,this.operator=this.value.trim()?this.value:" ",delete this.value,this.arguments=[n,l],this.loc&&(this.loc=[n.loc[0],l.loc[1]]),this}))}Ge(Se),Je(":",80);const et=Je(",",80);Je("(WHITESPACE)",80);const tt=e=>{const t=et.lbp>0;return null!=e&&(et.lbp=e?80:0),t};function nt(){let e=1;return()=>"fxg"+e++}function lt(e,t){return null==e&&null==t||e===t}function rt(e,t){if(Array.isArray(e)!==Array.isArray(t)||e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!lt(e[n],t[n]))return!1;return!0}function ot(e,t){return!e&&!t||String(e).toLowerCase()===String(t).toLowerCase()}function ut(e,t){if((e.name||t.name)&&e.name!==t.name)return!1;if(e.columns||t.columns){if(e.table!==t.table)return!1;if(!rt(e.columns,t.columns))return!1;if(!rt(e.sections,t.sections))return!1}return!!(!e.range&&!t.range||lt(e.range.top,t.range.top)&&lt(e.range.bottom,t.range.bottom)&&lt(e.range.left,t.range.left)&&lt(e.range.right,t.range.right))&&!(!ot(e.context[0],t.context[0])||!ot(e.context[1],t.context[1]))}function it(e,t,n){if(e.context.length){if(1===e.context.length){const l=e.context[0];e.context=l===t||l===n?[n,t]:[n,l]}}else e.context=[n,t];return e}Ve("%"),Ve("#",(function(e){return ke(e)||Ze("# expects a reference"),this.type=c,this.operator=this.value,delete this.value,this.arguments=[e],this})),Qe("+"),Qe("-"),Qe("@"),Ke("^",50),Ke("*",40),Ke("/",40),Ke("+",30),Ke("-",30),Ke("&",20),Ke("=",10),Ke("<",10),Ke(">",10),Ke("<=",10),Ke(">=",10),Ke("<>",10),Ge("Literal").nud=function(){const{type:e,value:n}=this;if(this.type="Literal",this.raw=n,"number"===e)this.value=+n;else if("bool"===e)this.value="TRUE"===n.toUpperCase();else if(e===t)this.type="ErrorLiteral",this.value=n.toUpperCase();else{if("string"!==e)throw new Error("Unsupported literal type: "+e);this.value=n.slice(1,-1).replace(/""/g,'"')}return this},Ge(a).nud=function(){return this.type=a,this},Ge(")"),Qe("(",(function(){const e=tt(!0),t=He(0);return Xe(")",t),tt(e),t})),Ge("(FUNCTION)").nud=function(){return this},Ke("(",90,(function(e){"(FUNCTION)"!==e.id&&Ze("Cannot call a "+e.type);const t=[];let n=!1;if(")"!==je.id){const e=tt(!1);for(;")"!==je.id;)if(Oe(je)&&Xe(),","===je.id)t.push(null),n=!0,Xe();else{const e=He(0);t.push(e),n=!1,","===je.id&&(Xe(","),n=!0)}tt(e)}n&&t.push(null);const l=je;return delete this.value,this.type=f,this.callee={type:"Identifier",name:e.value},e.loc&&(this.callee.loc=[...e.loc]),this.arguments=t,e.loc&&(this.loc=[e.loc[0],l.loc[1]]),Xe(")",this),this})),Ge("}"),Ge(";"),Qe("{",(function(){"}"===je.id&&Ze("Unexpected empty array");let e=[],t=!1;const n=[e],l=tt(!1);for(;!t;){if(Oe(je)&&Xe(),Ie(je))e.push(De.Literal.nud.call(je)),Xe();else if(qe&&ke(je))e.push(De[a].nud.call(je)),Xe();else if(Be&&_e(je)){const t=He(0);e.push(t)}else Ze(`Unexpected ${je.type} in array: ${je.value}`);","===je.id?Xe(","):";"===je.id?(Xe(";"),e=[],n.push(e)):t=!0}const r=je;return Xe("}"),tt(l),this.type="ArrayExpression",this.elements=n,this.loc&&(this.loc[1]=r.loc[1]),delete this.value,this}));const ct=(e,t,n)=>Math.min(Math.max(t,e),n);function st(e,t){return t?String(e+1):e?"["+e+"]":""}function at(e){let t=null,n=null,l=null,r=null;const o=/^R(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);o&&(o[1]?(t=parseInt(o[1],10),l=!1):o[2]?(t=parseInt(o[2],10)-1,l=!0):(t=0,l=!1),e=e.slice(o[0].length));const u=/^C(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);return u&&(u[1]?(n=parseInt(u[1],10),r=!1):u[2]?(n=parseInt(u[2],10)-1,r=!0):(n=0,r=!1),e=e.slice(u[0].length)),!o&&!u||e.length?null:[t,n,l,r]}function ft(e){let t=null;const[n,l]=e.split(":",2),r=at(n);if(r){const[e,n,o,u]=r;if(!l)return null!=e&&null==n?{r0:e,c0:null,r1:e,c1:null,$r0:o,$c0:!1,$r1:o,$c1:!1}:null==e&&null!=n?{r0:null,c0:n,r1:null,c1:n,$r0:!1,$c0:u,$r1:!1,$c1:u}:{r0:e||0,c0:n||0,r1:e||0,c1:n||0,$r0:o||!1,$c0:u||!1,$r1:o||!1,$c1:u||!1};{const r=at(l);if(!r)return null;{t={};const[l,i,c,s]=r;null!=e&&null!=l?(t.r0=o===c?Math.min(e,l):e,t.$r0=o,t.r1=o===c?Math.max(e,l):l,t.$r1=c):null!=e&&null==l?(t.r0=e,t.$r0=o,t.r1=null,t.$r1=o):null==e&&null!=l?(t.r0=l,t.$r0=c,t.r1=null,t.$r1=c):null==e&&null==l&&(t.r0=null,t.$r0=!1,t.r1=null,t.$r1=!1),null!=n&&null!=i?(t.c0=u===s?Math.min(n,i):n,t.$c0=u,t.c1=u===s?Math.max(n,i):i,t.$c1=s):null!=n&&null==i?(t.c0=n,t.$c0=u,t.c1=null,t.$c1=u):null==n&&null!=i?(t.c0=i,t.$c0=s,t.c1=null,t.$c1=s):null==n&&null==i&&(t.c0=null,t.$c0=!1,t.c1=null,t.$c1=!1)}}}return t}function pt(e){let{allowNamed:t=!0,allowTernary:n=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const l=C(e,{allowNamed:t,allowTernary:n,r1c1:!0});if(l&&(l.r0||l.name)){const e=l.r1?ft(l.r0+":"+l.r1):ft(l.r0);return l.name||e?(l.range=e,delete l.r0,delete l.r1,l):null}return null}function ht(e){return N(e)+(e.name?e.name:function(e){let{r0:t,c0:n,r1:l,c1:r}=e;const{$c0:o,$c1:u,$r0:i,$r1:c}=e,s=null==t,a=null==n;let f=null==l,p=null==r;if(t=ct(i?0:-1048575,0|t,1048575),n=ct(o?0:-16383,0|n,16383),!s&&f&&!a&&p?(l=t,f=!1,r=n,p=!1):(l=ct(c?0:-1048575,0|l,1048575),r=ct(u?0:-16383,0|r,16383)),0===t&&l>=1048575||s&&f){const e=st(n,o),t=st(r,u);return"C"+(e===t?e:e+":C"+t)}if(0===n&&r>=16383||a&&p){const e=st(t,i),n=st(l,c);return"R"+(e===n?e:e+":R"+n)}const h=st(t,i),g=st(l,c),d=st(n,o),$=st(r,u);return s||f||a||p?(s?"":"R"+h)+(a?"":"C"+d)+":"+(f?"":"R"+g)+(p?"":"C"+$):h!==g||d!==$?"R"+h+"C"+d+":R"+g+"C"+$:"R"+h+"C"+d}(e.range))}const gt=(e,t,n)=>null==t?null:e?t:t-n,dt={withLocation:!1,mergeRefs:!1,allowTernary:!0,r1c1:!1};function $t(e,t,n,l){let r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=e;if(null!=o&&!t){if(o=n+e,o<0){if(!r)return NaN;o=l+o+1}if(o>l){if(!r)return NaN;o-=l+1}}return o}const yt={wrapEdges:!0,mergeRefs:!0};const xt=Object.freeze({OPERATOR:e,BOOLEAN:"bool",ERROR:t,NUMBER:"number",FUNCTION:"func",NEWLINE:"newline",WHITESPACE:"whitespace",STRING:"string",CONTEXT:n,CONTEXT_QUOTE:"context_quote",REF_RANGE:"range",REF_BEAM:l,REF_TERNARY:r,REF_NAMED:o,REF_STRUCT:u,FX_PREFIX:"fx_prefix",UNKNOWN:i}),vt=Object.freeze({UNARY:c,BINARY:s,REFERENCE:a,LITERAL:"Literal",ERROR:"ErrorLiteral",CALL:f,ARRAY:"ArrayExpression",IDENTIFIER:"Identifier"});exports.MAX_COLS=16383,exports.MAX_ROWS=1048575,exports.addA1RangeBounds=M,exports.addTokenMeta=function(e){let{sheetName:t="",workbookName:n=""}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const o=[];let c=null;const s=nt(),a=[],f=()=>o.length+(c?1:0);return e.forEach(((e,p)=>{if(e.index=p,e.depth=f(),"("===e.value)o.push(e),e.depth=f();else if(")"===e.value){const t=o.pop();if(t){const n=s();e.groupId=n,e.depth=t.depth,t.groupId=n}else e.error=!0}else if("{"===e.value)c?e.error=!0:(c=e,e.depth=f());else if("}"===e.value){if(c){const t=s();e.groupId=t,e.depth=c.depth,c.groupId=t}else e.error=!0;c=null}else if("range"===e.type||e.type===l||e.type===r||e.type===u){const l=e.type===u?Z(e.value,{allowTernary:!0}):F(e.value,{allowTernary:!0});if(l&&(l.range||l.columns)){l.source=e.value,it(l,t,n);const r=a.find((e=>ut(e,l)));r?e.groupId=r.groupId:(l.groupId=s(),e.groupId=l.groupId,a.push(l))}}else e.type===i&&(e.error=!0)})),e},exports.fixRanges=function e(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{addBounds:!1};if("string"==typeof t)return e(Ne(t,n),n).map((e=>e.value)).join("");if(!Array.isArray(t))throw new Error("fixRanges expects an array of tokens");const{addBounds:l,r1c1:r}=n;if(r)throw new Error("fixRanges does not have an R1C1 mode");let o=0;return t.map((e=>{const t={...e};e.loc&&(t.loc=[...e.loc]);let n=0;if(t.type===u){const e=H(Z(t.value));n=e.length-t.value.length,t.value=e}else if(be(t)){const e=F(t.value,{allowTernary:!0}),r=e.range;l&&M(r);const o=S(e);n=o.length-t.value.length,t.value=o}return o||n?(t.loc&&(t.loc[0]+=o),o+=n,t.loc&&(t.loc[1]+=o)):o+=n,t}))},exports.fromCol=L,exports.isError=Le,exports.isFunction=_e,exports.isFxPrefix=Ue,exports.isLiteral=Ie,exports.isOperator=Fe,exports.isRange=be,exports.isReference=Te,exports.isWhitespace=Oe,exports.mergeRefTokens=me,exports.nodeTypes=vt,exports.parse=function(e,t){if("string"==typeof e)ze=Ne(e,{withLocation:!0,...t,mergeRefs:!0});else{if(!Array.isArray(e))throw new Error("Parse requires a string or array of tokens.");ze=e}for(qe=t?.permitArrayRanges,Be=t?.permitArrayCalls,We=0;Oe(ze[We])||Ue(ze[We]);)We++;Xe(),tt(!0);const n=He(0);return Xe(Se),n},exports.parseA1Ref=F,exports.parseR1C1Ref=pt,exports.parseStructRef=Z,exports.stringifyA1Ref=S,exports.stringifyR1C1Ref=ht,exports.stringifyStructRef=H,exports.toCol=O,exports.tokenTypes=xt,exports.tokenize=Ne,exports.translateToA1=function(e,n){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:yt;const r=U(n),o="string"==typeof e,u={...yt,...l},i=o?Ne(e,{withLocation:!1,mergeRefs:u.mergeRefs,allowTernary:!0,r1c1:!0}):e;let c=0;return i.forEach((e=>{if(be(e)){const n=e.value,l=pt(n,{allowTernary:!0}),o=l.range,i={},s=$t(o.r0,o.$r0,r.top,1048575,u.wrapEdges),a=$t(o.r1,o.$r1,r.top,1048575,u.wrapEdges);s>a?(i.top=a,i.$top=o.$r1,i.bottom=s,i.$bottom=o.$r0):(i.top=s,i.$top=o.$r0,i.bottom=a,i.$bottom=o.$r1);const f=$t(o.c0,o.$c0,r.left,16383,u.wrapEdges),p=$t(o.c1,o.$c1,r.left,16383,u.wrapEdges);f>p?(i.left=p,i.$left=o.$c1,i.right=f,i.$right=o.$c0):(i.left=f,i.$left=o.$c0,i.right=p,i.$right=o.$c1),isNaN(s)||isNaN(a)||isNaN(f)||isNaN(p)?(e.type=t,e.value="#REF!",delete e.groupId):(l.range=i,e.value=S(l)),e.loc&&(e.loc[0]+=c,c+=e.value.length-n.length,e.loc[1]+=c)}else c&&e.loc&&(e.loc[0]+=c,e.loc[1]+=c)})),o?i.map((e=>e.value)).join(""):i},exports.translateToR1C1=function(e,t){const{top:n,left:l}=U(t),r="string"==typeof e,o=r?Ne(e,dt):e;let u=0;return o.forEach((e=>{if(be(e)){const t=e.value,r=F(t,{allowTernary:!0}),o=r.range,i={};i.r0=gt(o.$top,o.top,n),i.r1=gt(o.$bottom,o.bottom,n),i.c0=gt(o.$left,o.left,l),i.c1=gt(o.$right,o.right,l),i.$r0=o.$top,i.$r1=o.$bottom,i.$c0=o.$left,i.$c1=o.$right,r.range=i,e.value=ht(r),e.loc&&(e.loc[0]+=u,u+=e.value.length-t.length,e.loc[1]+=u)}else u&&e.loc&&(e.loc[0]+=u,e.loc[1]+=u)})),r?o.map((e=>e.value)).join(""):o};
2
2
  //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnguanMiLCJzb3VyY2VzIjpbXSwic291cmNlc0NvbnRlbnQiOltdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
package/docs/API.md CHANGED
@@ -1,4 +1,4 @@
1
- # @borgar/fx API
1
+ # _fx_ API
2
2
 
3
3
  ## Constants
4
4
 
@@ -362,7 +362,7 @@ Parses a string formula or list of tokens into an AST.
362
362
 
363
363
  The parser requires `mergeRefs` to have been `true` in tokenlist options, because it does not recognize reference context tokens.
364
364
 
365
- The AST Abstract Syntax Tree's format is documented in [AST format.md][AST format.md]
365
+ The AST Abstract Syntax Tree's format is documented in [AST_format.md][./AST_format.md]
366
366
 
367
367
  **See also:** [nodeTypes](#nodeTypes).
368
368
 
@@ -375,7 +375,8 @@ The AST Abstract Syntax Tree's format is documented in [AST format.md][AST forma
375
375
  | _[options]_.allowNamed | `boolean` | `true` | Enable parsing names as well as ranges. |
376
376
  | _[options]_.allowTernary | `boolean` | `false` | Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md. |
377
377
  | _[options]_.negativeNumbers | `boolean` | `true` | Merges unary minuses with their immediately following number tokens (`-`,`1`) => `-1` (alternatively these will be unary operations in the tree). |
378
- | _[options]_.permitArrayRanges | `boolean` | `false` | Ranges are allowed as elements of arrays. This is a features in Google Sheets while Excel does not support it. |
378
+ | _[options]_.permitArrayRanges | `boolean` | `false` | Ranges are allowed as elements of arrays. This is a feature in Google Sheets while Excel does not allow it. |
379
+ | _[options]_.permitArrayCalls | `boolean` | `false` | Function calls are allowed as elements of arrays. This is a feature in Google Sheets while Excel does not allow it. |
379
380
  | _[options]_.r1c1 | `boolean` | `false` | Ranges are expected to be in the R1C1 style format rather than the more popular A1 style. |
380
381
  | _[options]_.withLocation | `boolean` | `true` | Nodes will include source position offsets to the tokens: `{ loc: [ start, end ] }` |
381
382
 
@@ -1,5 +1,6 @@
1
- import { REF_RANGE, REF_BEAM, REF_TERNARY, UNKNOWN } from './constants.js';
1
+ import { REF_RANGE, REF_BEAM, REF_TERNARY, UNKNOWN, REF_STRUCT } from './constants.js';
2
2
  import { parseA1Ref } from './a1.js';
3
+ import { parseStructRef } from './sr.js';
3
4
 
4
5
  function getIDer () {
5
6
  let i = 1;
@@ -13,6 +14,18 @@ function sameValue (a, b) {
13
14
  return a === b;
14
15
  }
15
16
 
17
+ function sameArray (a, b) {
18
+ if ((Array.isArray(a) !== Array.isArray(b)) || a.length !== b.length) {
19
+ return false;
20
+ }
21
+ for (let i = 0; i < a.length; i++) {
22
+ if (!sameValue(a[i], b[i])) {
23
+ return false;
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+
16
29
  function sameStr (a, b) {
17
30
  if (!a && !b) {
18
31
  return true;
@@ -25,6 +38,18 @@ function isEquivalent (refA, refB) {
25
38
  if ((refA.name || refB.name) && refA.name !== refB.name) {
26
39
  return false;
27
40
  }
41
+ // if structured
42
+ if ((refA.columns || refB.columns)) {
43
+ if (refA.table !== refB.table) {
44
+ return false;
45
+ }
46
+ if (!sameArray(refA.columns, refB.columns)) {
47
+ return false;
48
+ }
49
+ if (!sameArray(refA.sections, refB.sections)) {
50
+ return false;
51
+ }
52
+ }
28
53
  // if ranged, range must have the same dimensions (we don't care about $)
29
54
  if (refA.range || refB.range) {
30
55
  if (
@@ -46,6 +71,23 @@ function isEquivalent (refA, refB) {
46
71
  return true;
47
72
  }
48
73
 
74
+ function addContext (ref, sheetName, workbookName) {
75
+ if (!ref.context.length) {
76
+ ref.context = [ workbookName, sheetName ];
77
+ }
78
+ else if (ref.context.length === 1) {
79
+ const scope = ref.context[0];
80
+ if (scope === sheetName || scope === workbookName) {
81
+ ref.context = [ workbookName, sheetName ];
82
+ }
83
+ else {
84
+ // a single scope on a non-named range is going to be a sheet name
85
+ ref.context = [ workbookName, scope ];
86
+ }
87
+ }
88
+ return ref;
89
+ }
90
+
49
91
  /**
50
92
  * Runs through a list of tokens and adds extra attributes such as matching
51
93
  * parens and ranges.
@@ -140,23 +182,18 @@ export function addTokenMeta (tokens, { sheetName = '', workbookName = '' } = {}
140
182
  }
141
183
  arrayStart = null;
142
184
  }
143
- else if (token.type === REF_RANGE || token.type === REF_BEAM || token.type === REF_TERNARY) {
144
- const ref = parseA1Ref(token.value, { allowTernary: true });
145
- if (ref && ref.range) {
185
+ else if (
186
+ token.type === REF_RANGE ||
187
+ token.type === REF_BEAM ||
188
+ token.type === REF_TERNARY ||
189
+ token.type === REF_STRUCT
190
+ ) {
191
+ const ref = (token.type === REF_STRUCT)
192
+ ? parseStructRef(token.value, { allowTernary: true })
193
+ : parseA1Ref(token.value, { allowTernary: true });
194
+ if (ref && (ref.range || ref.columns)) {
146
195
  ref.source = token.value;
147
- if (!ref.context.length) {
148
- ref.context = [ workbookName, sheetName ];
149
- }
150
- else if (ref.context.length === 1) {
151
- const scope = ref.context[0];
152
- if (scope === sheetName || scope === workbookName) {
153
- ref.context = [ workbookName, sheetName ];
154
- }
155
- else {
156
- // a single scope on a non-named range is going to be a sheet name
157
- ref.context = [ workbookName, scope ];
158
- }
159
- }
196
+ addContext(ref, sheetName, workbookName);
160
197
  const known = knownRefs.find(d => isEquivalent(d, ref));
161
198
  if (known) {
162
199
  token.groupId = known.groupId;
@@ -1,5 +1,5 @@
1
1
  import { test, Test } from 'tape';
2
- import { FX_PREFIX, OPERATOR, NUMBER, REF_RANGE, REF_BEAM, FUNCTION, WHITESPACE } from './constants.js';
2
+ import { FX_PREFIX, OPERATOR, NUMBER, REF_RANGE, REF_BEAM, FUNCTION, WHITESPACE, REF_STRUCT } from './constants.js';
3
3
  import { addTokenMeta } from './addTokenMeta.js';
4
4
  import { tokenize } from './lexer.js';
5
5
 
@@ -106,5 +106,14 @@ test('add extra meta to operators', t => {
106
106
  { index: 17, depth: 1, type: OPERATOR, value: ')', groupId: 'fxg3' }
107
107
  ], { sheetName: 'Sheet1', workbookName: 'foo' });
108
108
 
109
+ t.isMetaTokens('=table[#all]+table[foobar]+table[[#All]]', [
110
+ { index: 0, depth: 0, type: FX_PREFIX, value: '=' },
111
+ { index: 1, depth: 0, type: REF_STRUCT, value: 'table[#all]', groupId: 'fxg1' },
112
+ { index: 2, depth: 0, type: OPERATOR, value: '+' },
113
+ { index: 3, depth: 0, type: REF_STRUCT, value: 'table[foobar]', groupId: 'fxg2' },
114
+ { index: 4, depth: 0, type: OPERATOR, value: '+' },
115
+ { index: 5, depth: 0, type: REF_STRUCT, value: 'table[[#All]]', groupId: 'fxg1' }
116
+ ], { sheetName: 'Sheet1', workbookName: 'foo' });
117
+
109
118
  t.end();
110
119
  });
package/lib/parser.js CHANGED
@@ -22,7 +22,11 @@ import {
22
22
  ERROR_LITERAL,
23
23
  CALL,
24
24
  ARRAY,
25
- IDENTIFIER
25
+ IDENTIFIER,
26
+ NUMBER,
27
+ BOOLEAN,
28
+ ERROR,
29
+ STRING
26
30
  } from './constants.js';
27
31
 
28
32
  import { tokenize } from './lexer.js';
@@ -59,9 +63,9 @@ const isReferenceToken = token => {
59
63
  };
60
64
 
61
65
  const isReferenceNode = node => {
62
- return (
66
+ return (!!node) && (
63
67
  (node.type === REFERENCE) ||
64
- (node.type === ERROR_LITERAL && node.value === '#REF!') ||
68
+ ((node.type === ERROR_LITERAL || node.type === ERROR) && node.value === '#REF!') ||
65
69
  (node.type === BINARY && (
66
70
  node.operator === ':' ||
67
71
  node.operator === ' ' ||
@@ -76,10 +80,12 @@ let currentNode;
76
80
  let tokens;
77
81
  let tokenIndex;
78
82
  let permitArrayRanges = false;
83
+ let permitArrayCalls = false;
79
84
 
80
85
  function halt (message) {
81
- const err = new SyntaxError(message);
86
+ const err = new Error(message);
82
87
  err.source = tokens.map(d => d.value).join('');
88
+ err.sourceOffset = tokens.slice(0, tokenIndex).reduce((a, d) => a + d.value, '').length;
83
89
  throw err;
84
90
  }
85
91
 
@@ -99,16 +105,19 @@ function refIsUpcoming () {
99
105
  return isReferenceToken(next);
100
106
  }
101
107
 
102
- function advance (expectNext = null) {
108
+ function advance (expectNext = null, leftNode = null) {
103
109
  if (expectNext && expectNext !== currentNode.id) {
104
110
  halt(`Expected ${expectNext} but got ${currentNode.id}`);
105
111
  }
106
112
  // look ahead to see if we have ( ( " ", "(" )+ REF )
107
113
  if (isWhitespace(tokens[tokenIndex])) {
108
114
  // potential intersection operation
109
- if (!refIsUpcoming()) {
115
+ const possibleWSOp = isReferenceNode(leftNode) && refIsUpcoming();
116
+ if (!possibleWSOp) {
110
117
  // ignore whitespace
111
- while (isWhitespace(tokens[tokenIndex])) { tokenIndex++; }
118
+ while (isWhitespace(tokens[tokenIndex])) {
119
+ tokenIndex++;
120
+ }
112
121
  }
113
122
  }
114
123
  // EOT
@@ -159,13 +168,12 @@ function advance (expectNext = null) {
159
168
  }
160
169
 
161
170
  function expression (rbp) {
162
- let left;
163
171
  let t = currentNode;
164
- advance();
165
- left = t.nud();
172
+ advance(null, t);
173
+ let left = t.nud();
166
174
  while (rbp < currentNode.lbp) {
167
175
  t = currentNode;
168
- advance();
176
+ advance(null, t);
169
177
  left = t.led(left);
170
178
  }
171
179
  return left;
@@ -173,7 +181,7 @@ function expression (rbp) {
173
181
 
174
182
  const original_symbol = {
175
183
  // null denotation
176
- nud: () => halt('Undefined'),
184
+ nud: () => halt('Invalid syntax'), // Undefined
177
185
  // left denotation
178
186
  led: () => halt('Missing operator')
179
187
  };
@@ -312,17 +320,17 @@ symbol(LITERAL).nud = function () {
312
320
  const { type, value } = this;
313
321
  this.type = LITERAL;
314
322
  this.raw = value;
315
- if (type === 'number') { // tokenTypes.NUMBER
323
+ if (type === NUMBER) {
316
324
  this.value = +value;
317
325
  }
318
- else if (type === 'bool') { // tokenTypes.BOOLEAN
326
+ else if (type === BOOLEAN) {
319
327
  this.value = value.toUpperCase() === 'TRUE';
320
328
  }
321
- else if (type === 'error') { // tokenTypes.ERROR
329
+ else if (type === ERROR) {
322
330
  this.type = ERROR_LITERAL;
323
331
  this.value = value.toUpperCase();
324
332
  }
325
- else if (type === 'string') { // tokenTypes.STRING
333
+ else if (type === STRING) {
326
334
  // FIXME: throw an error if the string is unterminated
327
335
  this.value = value.slice(1, -1).replace(/""/g, '"');
328
336
  }
@@ -341,7 +349,7 @@ symbol(')');
341
349
  prefix('(', function () {
342
350
  const prevState = unionRefs(true);
343
351
  const e = expression(0);
344
- advance(')');
352
+ advance(')', e);
345
353
  unionRefs(prevState);
346
354
  return e;
347
355
  });
@@ -359,6 +367,9 @@ infix('(', 90, function (left) {
359
367
  if (currentNode.id !== ')') {
360
368
  const prevState = unionRefs(false);
361
369
  while (currentNode.id !== ')') {
370
+ if (isWhitespace(currentNode)) {
371
+ advance();
372
+ }
362
373
  if (currentNode.id === ',') {
363
374
  args.push(null);
364
375
  lastWasComma = true;
@@ -380,7 +391,6 @@ infix('(', 90, function (left) {
380
391
  args.push(null);
381
392
  }
382
393
  const closeParen = currentNode;
383
- advance(')');
384
394
  delete this.value;
385
395
  this.type = CALL;
386
396
  this.callee = {
@@ -394,6 +404,7 @@ infix('(', 90, function (left) {
394
404
  if (left.loc) {
395
405
  this.loc = [ left.loc[0], closeParen.loc[1] ];
396
406
  }
407
+ advance(')', this);
397
408
  return this;
398
409
  });
399
410
 
@@ -409,19 +420,28 @@ prefix('{', function () {
409
420
  const rows = [ row ];
410
421
  const prevState = unionRefs(false);
411
422
  while (!done) {
423
+ if (isWhitespace(currentNode)) {
424
+ advance();
425
+ }
412
426
  // arrays allow only literals, ranges (in GSheets) and ,;: operators.
413
427
  // FIXME: if { negativeNumbers: false } we must consume minuses as well.
414
428
  // Excel allows ={-1} but not ={(-1)} and ={1%}
415
429
  if (isLiteral(currentNode)) {
416
430
  row.push(symbolTable[LITERAL].nud.call(currentNode));
431
+ advance();
417
432
  }
418
433
  else if (permitArrayRanges && isReferenceNode(currentNode)) {
419
434
  row.push(symbolTable[REFERENCE].nud.call(currentNode));
435
+ advance();
436
+ }
437
+ else if (permitArrayCalls && isFunction(currentNode)) {
438
+ const arg = expression(0);
439
+ row.push(arg);
440
+ // FIXME: need to skip WS here?
420
441
  }
421
442
  else {
422
443
  halt(`Unexpected ${currentNode.type} in array: ${currentNode.value}`);
423
444
  }
424
- advance();
425
445
  if (currentNode.id === ',') {
426
446
  // next item
427
447
  advance(',');
@@ -463,7 +483,8 @@ prefix('{', function () {
463
483
  * @param {boolean} [options.allowNamed=true] Enable parsing names as well as ranges.
464
484
  * @param {boolean} [options.allowTernary=false] Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md.
465
485
  * @param {boolean} [options.negativeNumbers=true] Merges unary minuses with their immediately following number tokens (`-`,`1`) => `-1` (alternatively these will be unary operations in the tree).
466
- * @param {boolean} [options.permitArrayRanges=false] Ranges are allowed as elements of arrays. This is a features in Google Sheets while Excel does not support it.
486
+ * @param {boolean} [options.permitArrayRanges=false] Ranges are allowed as elements of arrays. This is a feature in Google Sheets while Excel does not allow it.
487
+ * @param {boolean} [options.permitArrayCalls=false] Function calls are allowed as elements of arrays. This is a feature in Google Sheets while Excel does not allow it.
467
488
  * @param {boolean} [options.r1c1=false] Ranges are expected to be in the R1C1 style format rather than the more popular A1 style.
468
489
  * @param {boolean} [options.withLocation=true] Nodes will include source position offsets to the tokens: `{ loc: [ start, end ] }`
469
490
  * @return {Object} An AST of nodes
@@ -482,8 +503,10 @@ export function parse (source, options) {
482
503
  else {
483
504
  throw new Error('Parse requires a string or array of tokens.');
484
505
  }
485
- // allow ranges in literal arrays?
506
+ // allow ranges in array "literals"?
486
507
  permitArrayRanges = options?.permitArrayRanges;
508
+ // allow calls in arrays "literals"?
509
+ permitArrayCalls = options?.permitArrayCalls;
487
510
  // set index to start
488
511
  tokenIndex = 0;
489
512
  // discard redundant whitespace and = prefix
@@ -220,6 +220,25 @@ test('parse array literals', t => {
220
220
  t.isInvalidExpr('{1,}');
221
221
  t.isInvalidExpr('{,1}');
222
222
  t.isInvalidExpr('{;}');
223
+
224
+ // permitArrayCalls
225
+ t.isParsed('={1234; UNIQUE(A:A)}',
226
+ { type: 'ArrayExpression', elements: [
227
+ [ { type: 'Literal', value: 1234, raw: '1234' } ],
228
+ [ { type: 'CallExpression', callee: { type: 'Identifier', name: 'UNIQUE' }, arguments: [
229
+ { type: 'ReferenceIdentifier', value: 'A:A' }
230
+ ] } ] ] },
231
+ { permitArrayCalls: true });
232
+ // permitArrayCalls can be nested
233
+ t.isParsed('={SUM({1,2}),3}',
234
+ { type: 'ArrayExpression', elements: [
235
+ [ { type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
236
+ { type: 'ArrayExpression', elements: [ [
237
+ { type: 'Literal', value: 1, raw: '1' },
238
+ { type: 'Literal', value: 2, raw: '2' } ] ] }
239
+ ] },
240
+ { type: 'Literal', value: 3, raw: '3' } ] ] },
241
+ { permitArrayCalls: true });
223
242
  t.end();
224
243
  });
225
244
 
@@ -775,3 +794,37 @@ test('position information is correct', t => {
775
794
  );
776
795
  t.end();
777
796
  });
797
+
798
+ test('does not tolerate unterminated tokens', t => {
799
+ // whitespace in arrays
800
+ t.isParsed('=SORT({ A:A, B:B })',
801
+ { type: 'CallExpression', callee: { type: 'Identifier', name: 'SORT' },
802
+ arguments: [
803
+ { type: 'ArrayExpression', elements: [
804
+ [ { type: 'ReferenceIdentifier', value: 'A:A' },
805
+ { type: 'ReferenceIdentifier', value: 'B:B' } ] ] } ] },
806
+ { permitArrayRanges: true });
807
+ // whitespace in arguments
808
+ t.isParsed('=A2:A5=XLOOKUP(B1,C:C, D:D)',
809
+ { type: 'BinaryExpression', operator: '=', arguments: [
810
+ { type: 'ReferenceIdentifier', value: 'A2:A5' },
811
+ { type: 'CallExpression', callee: { type: 'Identifier', name: 'XLOOKUP' },
812
+ arguments: [
813
+ { type: 'ReferenceIdentifier', value: 'B1' },
814
+ { type: 'ReferenceIdentifier', value: 'C:C' },
815
+ { type: 'ReferenceIdentifier', value: 'D:D' } ] } ] },
816
+ { permitArrayRanges: true });
817
+ // whitespace surrounding comma
818
+ t.isParsed('=SUM(12 , B:B)',
819
+ { type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
820
+ { type: 'Literal', value: 12, raw: '12' },
821
+ { type: 'ReferenceIdentifier', value: 'B:B' } ] },
822
+ { permitArrayCalls: true });
823
+ // whitespace tailing operator
824
+ t.isParsed('=A:A= C1',
825
+ { type: 'BinaryExpression', operator: '=', arguments: [
826
+ { type: 'ReferenceIdentifier', value: 'A:A' },
827
+ { type: 'ReferenceIdentifier', value: 'C1' } ] },
828
+ { permitArrayCalls: true });
829
+ t.end();
830
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@borgar/fx",
3
- "version": "4.0.0",
3
+ "version": "4.2.0",
4
4
  "description": "Utilities for working with Excel formulas",
5
5
  "main": "dist/fx.js",
6
6
  "module": "lib/index.js",
@@ -15,7 +15,7 @@
15
15
  "version": "npm run build",
16
16
  "lint": "eslint lib/*.js",
17
17
  "test": "tape lib/*.spec.js | tap-min",
18
- "build:docs": "echo '# @borgar/fx API\n'>docs/API.md; jsdoc -c .jsdoc/config.json -d console lib>>docs/API.md",
18
+ "build:docs": "echo '# _fx_ API\n'>docs/API.md; jsdoc -c .jsdoc/config.json -d console lib>>docs/API.md",
19
19
  "build": "NODE_ENV=production rollup -c"
20
20
  },
21
21
  "repository": {