diff --git a/dist/lindenmayer.browser.js b/dist/lindenmayer.browser.js index 8b2e177..c2fca90 100644 --- a/dist/lindenmayer.browser.js +++ b/dist/lindenmayer.browser.js @@ -127,7 +127,7 @@ function normalizeProduction(p, forceObjects) { return p; } -function LSystem({ axiom = '', productions, finals, branchSymbols = '', ignoredSymbols = '', allowClassicSyntax = true, classicParametricSyntax = false, forceObjects = false, debug = false }) { +function LSystem({ axiom = '', productions, finals, branchSymbols = '[]', ignoredSymbols = '+-&^/|\\', allowClassicSyntax = true, classicParametricSyntax = false, forceObjects = false, debug = false }) { // TODO: forceObject to be more intelligent based on other productions?? @@ -167,7 +167,7 @@ function LSystem({ axiom = '', productions, finals, branchSymbols = '', ignoredS // Apply production transformers and normalizations if (this.allowClassicSyntax === true) { - newProduction = transformClassicCSProduction(newProduction, this.ignoredSymbols); + newProduction = transformClassicCSProduction(newProduction); } newProduction = normalizeProduction(newProduction, this.forceObjects); @@ -253,11 +253,11 @@ function LSystem({ axiom = '', productions, finals, branchSymbols = '', ignoredS precheck = false; } else if (contextSensitive) { if (p.leftCtx !== undefined && p.rightCtx !== undefined) { - precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols: '[]' }).result && this.match({ direction: 'right', match: p.rightCtx, index: index, branchSymbols: '[]', ignoredSymbols: ignoredSymbols }).result; + precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols, ignoredSymbols }).result; } else if (p.leftCtx !== undefined) { - precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols: '[]' }).result; + precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols, ignoredSymbols }).result; } else if (p.rightCtx !== undefined) { - precheck = this.match({ direction: 'right', match: p.rightCtx, index: index, branchSymbols: '[]' }).result; + precheck = this.match({ direction: 'right', match: p.rightCtx, index: index, branchSymbols, ignoredSymbols }).result; } } diff --git a/dist/lindenmayer.browser.min.js b/dist/lindenmayer.browser.min.js index c52e5ab..07e712c 100644 --- a/dist/lindenmayer.browser.min.js +++ b/dist/lindenmayer.browser.min.js @@ -1 +1 @@ -var LSystem=function(){"use strict";function t(t){let s,i=t[0].match(/(.+)<(.)/),o=t[0].match(/(.)>(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function s(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function i(t,i){return t[1]=function t(i,o){if(i.hasOwnProperty("successors"))for(var e=0;e{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(s,o,e=!1){let r=[s,o];if(void 0===r)throw new Error("no production specified.");if(o.successor&&o.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(r=t(r,this.ignoredSymbols)),(r=i(r,this.forceObjects))[1].isStochastic=void 0!==r[1].successors&&r[1].successors.every(t=>void 0!==t.weight),r[1].isStochastic){r[1].weightSum=0;for(let t of r[1].successors)r[1].weightSum+=t.weight}let n=r[0];if(!0===e&&this.productions.has(n)){let t=this.productions.get(n),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(r[1]),this.productions.set(n,t)}else this.productions.set(n,r[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let r=void 0!==t.leftCtx||void 0!==t.rightCtx,n=!1,a=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?a=!1:r&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result&&this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]",ignoredSymbols:c}).result:void 0!==t.leftCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result:void 0!==t.rightCtx&&(a=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]"}).result)),!1===a)n=!1;else if(t.successors){var h,l;t.isStochastic&&(l=Math.random()*t.weightSum,h=0);for(let e of t.successors){if(t.isStochastic&&(h+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=m=-1,l=e-1,f=s.length-1,d=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=m):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=m)):(g.push(l),f+=m)),f===d)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=n,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(o),this.clearProductions(),e&&this.setProductions(e),r&&this.setFinals(r),this}return LSystem.transformClassicStochasticProductions=function(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function s(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function i(t,i){return t[1]=function t(i,o){if(i.hasOwnProperty("successors"))for(var e=0;e{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(s,o,e=!1){let r=[s,o];if(void 0===r)throw new Error("no production specified.");if(o.successor&&o.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(r=t(r)),(r=i(r,this.forceObjects))[1].isStochastic=void 0!==r[1].successors&&r[1].successors.every(t=>void 0!==t.weight),r[1].isStochastic){r[1].weightSum=0;for(let t of r[1].successors)r[1].weightSum+=t.weight}let n=r[0];if(!0===e&&this.productions.has(n)){let t=this.productions.get(n),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(r[1]),this.productions.set(n,t)}else this.productions.set(n,r[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let r=void 0!==t.leftCtx||void 0!==t.rightCtx,a=!1,h=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?h=!1:r&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:n,ignoredSymbols:c}).result:void 0!==t.leftCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:n,ignoredSymbols:c}).result:void 0!==t.rightCtx&&(h=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:n,ignoredSymbols:c}).result)),!1===h)a=!1;else if(t.successors){var l,u;t.isStochastic&&(u=Math.random()*t.weightSum,l=0);for(let e of t.successors){if(t.isStochastic&&(l+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=d=-1,l=e-1,f=s.length-1,m=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=d):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=d)):(g.push(l),f+=d)),f===m)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=n,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(o),this.clearProductions(),e&&this.setProductions(e),r&&this.setFinals(r),this}return LSystem.transformClassicStochasticProductions=function(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function e(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function r(t,s){if(t.hasOwnProperty("successors"))for(var i=0;i{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(t,s,i=!1){let e=[t,s];if(void 0===e)throw new Error("no production specified.");if(s.successor&&s.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(e=o(e,this.ignoredSymbols)),(e=n(e,this.forceObjects))[1].isStochastic=void 0!==e[1].successors&&e[1].successors.every(t=>void 0!==t.weight),e[1].isStochastic){e[1].weightSum=0;for(let t of e[1].successors)e[1].weightSum+=t.weight}let r=e[0];if(!0===i&&this.productions.has(r)){let t=this.productions.get(r),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(e[1]),this.productions.set(r,t)}else this.productions.set(r,e[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let r=void 0!==t.leftCtx||void 0!==t.rightCtx,n=!1,a=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?a=!1:r&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result&&this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]",ignoredSymbols:c}).result:void 0!==t.leftCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result:void 0!==t.rightCtx&&(a=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]"}).result)),!1===a)n=!1;else if(t.successors){var h,l;t.isStochastic&&(l=Math.random()*t.weightSum,h=0);for(let e of t.successors){if(t.isStochastic&&(h+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=d=-1,l=e-1,f=s.length-1,m=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=d):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=d)):(g.push(l),f+=d)),f===m)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=r,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(t),this.clearProductions(),s&&this.setProductions(s),i&&this.setFinals(i),this}LSystem.transformClassicStochasticProductions=t,LSystem.transformClassicCSProduction=o,LSystem.transformClassicParametricAxiom=i,LSystem.testClassicParametricSyntax=s;export default LSystem; +function t(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function e(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function r(t,s){if(t.hasOwnProperty("successors"))for(var i=0;i{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(t,s,i=!1){let e=[t,s];if(void 0===e)throw new Error("no production specified.");if(s.successor&&s.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(e=o(e)),(e=n(e,this.forceObjects))[1].isStochastic=void 0!==e[1].successors&&e[1].successors.every(t=>void 0!==t.weight),e[1].isStochastic){e[1].weightSum=0;for(let t of e[1].successors)e[1].weightSum+=t.weight}let r=e[0];if(!0===i&&this.productions.has(r)){let t=this.productions.get(r),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(e[1]),this.productions.set(r,t)}else this.productions.set(r,e[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let n=void 0!==t.leftCtx||void 0!==t.rightCtx,a=!1,h=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?h=!1:n&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:r,ignoredSymbols:c}).result:void 0!==t.leftCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:r,ignoredSymbols:c}).result:void 0!==t.rightCtx&&(h=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:r,ignoredSymbols:c}).result)),!1===h)a=!1;else if(t.successors){var l,u;t.isStochastic&&(u=Math.random()*t.weightSum,l=0);for(let e of t.successors){if(t.isStochastic&&(l+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=d=-1,l=e-1,f=s.length-1,m=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=d):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=d)):(g.push(l),f+=d)),f===m)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=r,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(t),this.clearProductions(),s&&this.setProductions(s),i&&this.setFinals(i),this}LSystem.transformClassicStochasticProductions=t,LSystem.transformClassicCSProduction=o,LSystem.transformClassicParametricAxiom=i,LSystem.testClassicParametricSyntax=s;export default LSystem; diff --git a/dist/lindenmayer.js b/dist/lindenmayer.js index e510e83..66f8949 100644 --- a/dist/lindenmayer.js +++ b/dist/lindenmayer.js @@ -126,7 +126,7 @@ function normalizeProduction(p, forceObjects) { return p; } -function LSystem({ axiom = '', productions, finals, branchSymbols = '', ignoredSymbols = '', allowClassicSyntax = true, classicParametricSyntax = false, forceObjects = false, debug = false }) { +function LSystem({ axiom = '', productions, finals, branchSymbols = '[]', ignoredSymbols = '+-&^/|\\', allowClassicSyntax = true, classicParametricSyntax = false, forceObjects = false, debug = false }) { // TODO: forceObject to be more intelligent based on other productions?? @@ -166,7 +166,7 @@ function LSystem({ axiom = '', productions, finals, branchSymbols = '', ignoredS // Apply production transformers and normalizations if (this.allowClassicSyntax === true) { - newProduction = transformClassicCSProduction(newProduction, this.ignoredSymbols); + newProduction = transformClassicCSProduction(newProduction); } newProduction = normalizeProduction(newProduction, this.forceObjects); @@ -252,11 +252,11 @@ function LSystem({ axiom = '', productions, finals, branchSymbols = '', ignoredS precheck = false; } else if (contextSensitive) { if (p.leftCtx !== undefined && p.rightCtx !== undefined) { - precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols: '[]' }).result && this.match({ direction: 'right', match: p.rightCtx, index: index, branchSymbols: '[]', ignoredSymbols: ignoredSymbols }).result; + precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols, ignoredSymbols }).result; } else if (p.leftCtx !== undefined) { - precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols: '[]' }).result; + precheck = this.match({ direction: 'left', match: p.leftCtx, index: index, branchSymbols, ignoredSymbols }).result; } else if (p.rightCtx !== undefined) { - precheck = this.match({ direction: 'right', match: p.rightCtx, index: index, branchSymbols: '[]' }).result; + precheck = this.match({ direction: 'right', match: p.rightCtx, index: index, branchSymbols, ignoredSymbols }).result; } } diff --git a/dist/lindenmayer.min.js b/dist/lindenmayer.min.js index b6de4ae..2ff3604 100644 --- a/dist/lindenmayer.min.js +++ b/dist/lindenmayer.min.js @@ -1 +1 @@ -"use strict";function t(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function e(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function r(t,s){if(t.hasOwnProperty("successors"))for(var i=0;i{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(t,s,i=!1){let e=[t,s];if(void 0===e)throw new Error("no production specified.");if(s.successor&&s.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(e=o(e,this.ignoredSymbols)),(e=n(e,this.forceObjects))[1].isStochastic=void 0!==e[1].successors&&e[1].successors.every(t=>void 0!==t.weight),e[1].isStochastic){e[1].weightSum=0;for(let t of e[1].successors)e[1].weightSum+=t.weight}let r=e[0];if(!0===i&&this.productions.has(r)){let t=this.productions.get(r),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(e[1]),this.productions.set(r,t)}else this.productions.set(r,e[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let r=void 0!==t.leftCtx||void 0!==t.rightCtx,n=!1,a=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?a=!1:r&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result&&this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]",ignoredSymbols:c}).result:void 0!==t.leftCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result:void 0!==t.rightCtx&&(a=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]"}).result)),!1===a)n=!1;else if(t.successors){var h,l;t.isStochastic&&(l=Math.random()*t.weightSum,h=0);for(let e of t.successors){if(t.isStochastic&&(h+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=m=-1,l=e-1,f=s.length-1,d=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=m):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=m)):(g.push(l),f+=m)),f===d)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=r,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(t),this.clearProductions(),s&&this.setProductions(s),i&&this.setFinals(i),this}LSystem.transformClassicStochasticProductions=t,LSystem.transformClassicCSProduction=o,LSystem.transformClassicParametricAxiom=i,LSystem.testClassicParametricSyntax=s,module.exports=LSystem; +"use strict";function t(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function e(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function r(t,s){if(t.hasOwnProperty("successors"))for(var i=0;i{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(t,s,i=!1){let e=[t,s];if(void 0===e)throw new Error("no production specified.");if(s.successor&&s.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(e=o(e)),(e=n(e,this.forceObjects))[1].isStochastic=void 0!==e[1].successors&&e[1].successors.every(t=>void 0!==t.weight),e[1].isStochastic){e[1].weightSum=0;for(let t of e[1].successors)e[1].weightSum+=t.weight}let r=e[0];if(!0===i&&this.productions.has(r)){let t=this.productions.get(r),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(e[1]),this.productions.set(r,t)}else this.productions.set(r,e[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let n=void 0!==t.leftCtx||void 0!==t.rightCtx,a=!1,h=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?h=!1:n&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:r,ignoredSymbols:c}).result:void 0!==t.leftCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:r,ignoredSymbols:c}).result:void 0!==t.rightCtx&&(h=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:r,ignoredSymbols:c}).result)),!1===h)a=!1;else if(t.successors){var l,u;t.isStochastic&&(u=Math.random()*t.weightSum,l=0);for(let e of t.successors){if(t.isStochastic&&(l+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=d=-1,l=e-1,f=s.length-1,m=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=d):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=d)):(g.push(l),f+=d)),f===m)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=r,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(t),this.clearProductions(),s&&this.setProductions(s),i&&this.setFinals(i),this}LSystem.transformClassicStochasticProductions=t,LSystem.transformClassicCSProduction=o,LSystem.transformClassicParametricAxiom=i,LSystem.testClassicParametricSyntax=s,module.exports=LSystem; diff --git a/docs/examples/lindenmayer.js b/docs/examples/lindenmayer.js index c52e5ab..07e712c 100644 --- a/docs/examples/lindenmayer.js +++ b/docs/examples/lindenmayer.js @@ -1 +1 @@ -var LSystem=function(){"use strict";function t(t){let s,i=t[0].match(/(.+)<(.)/),o=t[0].match(/(.)>(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function s(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function i(t,i){return t[1]=function t(i,o){if(i.hasOwnProperty("successors"))for(var e=0;e{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(s,o,e=!1){let r=[s,o];if(void 0===r)throw new Error("no production specified.");if(o.successor&&o.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(r=t(r,this.ignoredSymbols)),(r=i(r,this.forceObjects))[1].isStochastic=void 0!==r[1].successors&&r[1].successors.every(t=>void 0!==t.weight),r[1].isStochastic){r[1].weightSum=0;for(let t of r[1].successors)r[1].weightSum+=t.weight}let n=r[0];if(!0===e&&this.productions.has(n)){let t=this.productions.get(n),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(r[1]),this.productions.set(n,t)}else this.productions.set(n,r[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let r=void 0!==t.leftCtx||void 0!==t.rightCtx,n=!1,a=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?a=!1:r&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result&&this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]",ignoredSymbols:c}).result:void 0!==t.leftCtx?a=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:"[]"}).result:void 0!==t.rightCtx&&(a=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:"[]"}).result)),!1===a)n=!1;else if(t.successors){var h,l;t.isStochastic&&(l=Math.random()*t.weightSum,h=0);for(let e of t.successors){if(t.isStochastic&&(h+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=m=-1,l=e-1,f=s.length-1,d=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=m):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=m)):(g.push(l),f+=m)),f===d)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=n,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(o),this.clearProductions(),e&&this.setProductions(e),r&&this.setFinals(r),this}return LSystem.transformClassicStochasticProductions=function(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t(.+)/);if(null===i&&null===o)return t;let e=t[1].successor||t[1].successors?t[1]:{successor:t[1]};return null!==i&&(s=i[2],e.leftCtx=i[1]),null!==o&&(s=o[1],e.rightCtx=o[2]),[s,e]}function s(t){if("string"!=typeof t&&t instanceof String==!1)return t;let s=[];for(let i of t)s.push({symbol:i});return s}function i(t,i){return t[1]=function t(i,o){if(i.hasOwnProperty("successors"))for(var e=0;e{if(void 0===s.symbol)throw console.log("found:",s),new Error("L-Systems that use only objects as symbols (eg: {symbol: 'F', params: []}), cant use string symbols (eg. 'F')! Check if you always return objects in your productions and no strings.");return t+s.symbol},""):JSON.stringify(this.axiom)},this.getStringResult=this.getString,this.setProduction=function(s,o,e=!1){let r=[s,o];if(void 0===r)throw new Error("no production specified.");if(o.successor&&o.successors)throw new Error('You can not have both a "successor" and a "successors" field in your production!');if(!0===this.allowClassicSyntax&&(r=t(r)),(r=i(r,this.forceObjects))[1].isStochastic=void 0!==r[1].successors&&r[1].successors.every(t=>void 0!==t.weight),r[1].isStochastic){r[1].weightSum=0;for(let t of r[1].successors)r[1].weightSum+=t.weight}let n=r[0];if(!0===e&&this.productions.has(n)){let t=this.productions.get(n),s=t.successor,i=t.successors;s&&!i&&(t={successors:[t]}),t.successors.push(r[1]),this.productions.set(n,t)}else this.productions.set(n,r[1])},this.setProductions=function(t){if(void 0===t)throw new Error("no production specified.");this.clearProductions();for(let s of Object.entries(t)){let t=s[0],i=s[1];this.setProduction(t,i,!0)}},this.clearProductions=function(){this.productions=new Map},this.setFinal=function(t,s){let i=[t,s];if(void 0===i)throw new Error("no final specified.");this.finals.set(i[0],i[1])},this.setFinals=function(t){if(void 0===t)throw new Error("no finals specified.");this.finals=new Map;for(let s in t)t.hasOwnProperty(s)&&this.setFinal(s,t[s])},this.getProductionResult=function(t,s,i,o,e=!1){let r=void 0!==t.leftCtx||void 0!==t.rightCtx,a=!1,h=!0;if(void 0!==t.condition&&!1===t.condition({index:s,currentAxiom:this.axiom,part:i,params:o})?h=!1:r&&(void 0!==t.leftCtx&&void 0!==t.rightCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:n,ignoredSymbols:c}).result:void 0!==t.leftCtx?h=this.match({direction:"left",match:t.leftCtx,index:s,branchSymbols:n,ignoredSymbols:c}).result:void 0!==t.rightCtx&&(h=this.match({direction:"right",match:t.rightCtx,index:s,branchSymbols:n,ignoredSymbols:c}).result)),!1===h)a=!1;else if(t.successors){var l,u;t.isStochastic&&(u=Math.random()*t.weightSum,l=0);for(let e of t.successors){if(t.isStochastic&&(l+=e.weight)0){var y=o;a=y[0],h=y[1]}}else{if("left"!==r)throw Error(r,"is not a valid direction for matching.");if(u=d=-1,l=e-1,f=s.length-1,m=-1,o.length>0){var p=o;h=p[0],a=p[1]}}for(;l=0;l+=u){let o=t[l].symbol||t[l],e=s[f];if(o===e){if((0===n||c>0)&&(o===a?(c++,n++,f+=d):o===h?(c=Math.max(0,c-1),n=Math.max(0,n-1),0===c&&(f+=d)):(g.push(l),f+=d)),f===m)return{result:!0,matchIndices:g}}else if(o===a)n++,c>0&&c++;else if(o===h)n=Math.max(0,n-1),c>0&&(c=Math.max(0,c-1));else if((0===n||c>0&&e!==h)&&!1===i.includes(o))return{result:!1,matchIndices:g}}return{result:!1,matchIndices:g}},this.ignoredSymbols=c,this.debug=u,this.branchSymbols=n,this.allowClassicSyntax=a,this.classicParametricSyntax=h,this.forceObjects=l,this.setAxiom(o),this.clearProductions(),e&&this.setProductions(e),r&&this.setFinals(r),this}return LSystem.transformClassicStochasticProductions=function(t){return function(){let s=t,i=s.length,o=Math.random();for(let t=0;t", "license": "MIT", "keywords": [ diff --git a/test/tests.js b/test/tests.js index 84ef01c..3b50fa5 100644 --- a/test/tests.js +++ b/test/tests.js @@ -48,7 +48,7 @@ describe('Basic String based L-Systems', function() { -describe('String based L-Systems with additional context-sensitive classic ABOP syntax productions', function() { +describe('String based L-Systems with additional context-sensitive classic ABOP syntax productions:', function() { it('Classic context sensitive syntax should work.', function() { let cs_LSystem7 = new LSystem({ @@ -72,15 +72,24 @@ it('Classic context sensitive syntax should work.', function() { }); - it('Left side, classic CS should work.', function() { - let cs_LSystem8 = new LSystem({ + it('Left side, classic CS should work with default ignored symbols.', function() { + let cs_LSystem8a = new LSystem({ + axiom: 'A+B+C[DE][-S-G[HI[JK]L-]M-NO]', + productions: {'BCG[H]M': 'Z'} + it('Right side, classic CS should work with default ignored symbols.', function() { + let cs_LSystem8a = new LSystem({ + axiom: 'A+B+C[DE][-S-G[HI[JK]L-]M-NO]', + productions: {'S>GM': 'Z'} }); - expect(cs_LSystem8.iterate()).to.equal('ABC[DE][ZG[HI[JK]L]MNO]'); + expect(cs_LSystem8a.iterate()).to.equal('A+B+C[DE][-Z-G[HI[JK]L-]M-NO]'); }); + + it('Right side, classic CS should work with explitly set ignored symbols.', function() { + let cs_LSystem8b = new LSystem({ + axiom: 'A+B+C[DE][-S-G[HI[JK]L-]M-NO]', + productions: {'S>GM': 'Z'}, + ignoredSymbols: '+-' + }); + expect(cs_LSystem8b.iterate()).to.equal('A+B+C[DE][-Z-G[HI[JK]L-]M-NO]'); + }); + });