From a98a1b35731e43a5c67c6c008107502f372fbc88 Mon Sep 17 00:00:00 2001 From: takumi4ichi Date: Sun, 2 Nov 2014 15:23:33 +0800 Subject: [PATCH 1/4] create gotoOperator(S, markedSymbol) cache of markedSymbols --- lib/jison.js | 9 +++++++-- package.json | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/jison.js b/lib/jison.js index 789307f6e..f181a7f08 100755 --- a/lib/jison.js +++ b/lib/jison.js @@ -733,16 +733,20 @@ lrGeneratorMixin.canonicalCollection = function canonicalCollection () { states = new Set(firstState), marked = 0, self = this, - itemSet; + itemSet, + markedSymbols; states.has = {}; states.has[firstState] = 0; while (marked !== states.size()) { itemSet = states.item(marked); marked++; + markedSymbols = {}; itemSet.forEach(function CC_itemSet_forEach (item) { - if (item.markedSymbol && item.markedSymbol !== self.EOF) + if (item.markedSymbol && !markedSymbols[item.markedSymbol] && item.markedSymbol !== self.EOF){ + markedSymbols[item.markedSymbol] = true; self.canonicalCollectionInsert(item.markedSymbol, itemSet, states, marked-1); + } }); } @@ -763,6 +767,7 @@ lrGeneratorMixin.canonicalCollectionInsert = function canonicalCollectionInsert itemSet.edges[symbol] = states.size(); // store goto transition for table states.push(g); g.predecessors[symbol] = [stateNum]; + console.log(states.size()); } else { itemSet.edges[symbol] = i; // store goto transition for table states.item(i).predecessors[symbol].push(stateNum); diff --git a/package.json b/package.json index e04ad7504..6cf63db02 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Zach Carter (http://zaa.ch)", "name": "jison", "description": "A parser generator with Bison's API", - "version": "0.4.15", + "version": "0.4.16", "keywords": [ "jison", "bison", From 90d6f5ea305be3401c72209dc14c4d1e759722d4 Mon Sep 17 00:00:00 2001 From: takumi4ichi Date: Wed, 5 Nov 2014 21:43:57 +0800 Subject: [PATCH 2/4] to avoid repeated calls to the closure --- lib/jison.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/jison.js b/lib/jison.js index f181a7f08..d6e072954 100755 --- a/lib/jison.js +++ b/lib/jison.js @@ -712,7 +712,7 @@ lrGeneratorMixin.closureOperation = function closureOperation (itemSet /*, closu return closureSet; }; -lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol) { +lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol, states) { var gotoSet = new this.ItemSet(), self = this; @@ -721,6 +721,11 @@ lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol) { gotoSet.push(new self.Item(item.production, item.dotPosition+1, item.follows, n)); } }); + if(states.has[gotoSet.valueOf()] !== undefined){ + return states.has[gotoSet.valueOf()]; + }else{ + states.has[gotoSet.valueOf()] = states.size(); + } return gotoSet.isEmpty() ? gotoSet : this.closureOperation(gotoSet); }; @@ -755,22 +760,19 @@ lrGeneratorMixin.canonicalCollection = function canonicalCollection () { // Pushes a unique state into the que. Some parsing algorithms may perform additional operations lrGeneratorMixin.canonicalCollectionInsert = function canonicalCollectionInsert (symbol, itemSet, states, stateNum) { - var g = this.gotoOperation(itemSet, symbol); - if (!g.predecessors) - g.predecessors = {}; - // add g to que if not empty or duplicate - if (!g.isEmpty()) { - var gv = g.valueOf(), - i = states.has[gv]; - if (i === -1 || typeof i === 'undefined') { - states.has[gv] = states.size(); + var g = this.gotoOperation(itemSet, symbol, states); + + if(typeof g === 'number'){ + itemSet.edges[symbol] = g; // store goto transition for table + states.item(g).predecessors[symbol].push(stateNum); + }else{ + if (!g.predecessors) + g.predecessors = {}; + // add g to que if not empty or duplicate + if (!g.isEmpty()) { itemSet.edges[symbol] = states.size(); // store goto transition for table states.push(g); g.predecessors[symbol] = [stateNum]; - console.log(states.size()); - } else { - itemSet.edges[symbol] = i; // store goto transition for table - states.item(i).predecessors[symbol].push(stateNum); } } }; From 5b15cc792bcdad2d9fa04abfb36b3aa4728ce9fd Mon Sep 17 00:00:00 2001 From: takumi4ichi Date: Wed, 5 Nov 2014 21:53:38 +0800 Subject: [PATCH 3/4] firstStateNoClosure.valueOf() is has[key] --- lib/jison.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/jison.js b/lib/jison.js index d6e072954..62d8c2162 100755 --- a/lib/jison.js +++ b/lib/jison.js @@ -734,7 +734,8 @@ lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol, states * */ lrGeneratorMixin.canonicalCollection = function canonicalCollection () { var item1 = new this.Item(this.productions[0], 0, [this.EOF]); - var firstState = this.closureOperation(new this.ItemSet(item1)), + var firstStateNoClosure = new this.ItemSet(item1), + firstState = this.closureOperation(firstStateNoClosure), states = new Set(firstState), marked = 0, self = this, @@ -742,7 +743,7 @@ lrGeneratorMixin.canonicalCollection = function canonicalCollection () { markedSymbols; states.has = {}; - states.has[firstState] = 0; + states.has[firstStateNoClosure.valueOf()] = 0; while (marked !== states.size()) { itemSet = states.item(marked); marked++; From 3271b0d62a3f0e4063b099a569a6edc7e142dc93 Mon Sep 17 00:00:00 2001 From: takumi4ichi Date: Thu, 6 Nov 2014 10:32:15 +0800 Subject: [PATCH 4/4] Optimized code structure: The closure is moved to the outside of the goto --- lib/jison.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/jison.js b/lib/jison.js index 62d8c2162..066b096f9 100755 --- a/lib/jison.js +++ b/lib/jison.js @@ -712,7 +712,7 @@ lrGeneratorMixin.closureOperation = function closureOperation (itemSet /*, closu return closureSet; }; -lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol, states) { +lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol) { var gotoSet = new this.ItemSet(), self = this; @@ -721,13 +721,8 @@ lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol, states gotoSet.push(new self.Item(item.production, item.dotPosition+1, item.follows, n)); } }); - if(states.has[gotoSet.valueOf()] !== undefined){ - return states.has[gotoSet.valueOf()]; - }else{ - states.has[gotoSet.valueOf()] = states.size(); - } - return gotoSet.isEmpty() ? gotoSet : this.closureOperation(gotoSet); + return gotoSet; }; /* Create unique set of item sets @@ -761,16 +756,19 @@ lrGeneratorMixin.canonicalCollection = function canonicalCollection () { // Pushes a unique state into the que. Some parsing algorithms may perform additional operations lrGeneratorMixin.canonicalCollectionInsert = function canonicalCollectionInsert (symbol, itemSet, states, stateNum) { - var g = this.gotoOperation(itemSet, symbol, states); + var g = this.gotoOperation(itemSet, symbol), + state = states.has[g.valueOf()]; - if(typeof g === 'number'){ - itemSet.edges[symbol] = g; // store goto transition for table - states.item(g).predecessors[symbol].push(stateNum); + if(state !== undefined){ + itemSet.edges[symbol] = state; // store goto transition for table + states.item(state).predecessors[symbol].push(stateNum); }else{ - if (!g.predecessors) - g.predecessors = {}; // add g to que if not empty or duplicate if (!g.isEmpty()) { + states.has[g.valueOf()] = states.size(); + g = this.closureOperation(g); + if (!g.predecessors) + g.predecessors = {}; itemSet.edges[symbol] = states.size(); // store goto transition for table states.push(g); g.predecessors[symbol] = [stateNum];