Refactoring parser code to remove global state

This allows canceling an in-progress render and moves some of the
rendering code to a more appropriate location.
This commit is contained in:
Jeff Avallone
2014-12-18 11:13:15 -05:00
parent 7de0a6490a
commit 80ec29cd6b
5 changed files with 96 additions and 69 deletions
+42 -11
View File
@@ -1,3 +1,5 @@
import Q from 'q';
import parser from './javascript/grammar.peg';
import Node from './javascript/node.js';
@@ -38,17 +40,46 @@ parser.Parser.RepeatOptional = { module: RepeatOptional };
parser.Parser.RepeatRequired = { module: RepeatRequired };
parser.Parser.RepeatSpec = { module: RepeatSpec };
parser.parse = (parse => {
return function() {
Subexp.resetCounter();
Node.reset();
export default class Parser {
constructor() {
this.state = {
groupCounter: 1,
renderCounter: 0,
maxCounter: 0,
cancelRender: false
};
}
return parse.apply(this, arguments);
};
})(parser.parse);
parse(expression) {
var deferred = Q.defer();
parser.cancel = () => {
Node.cancelRender = true;
};
setTimeout(() => {
Node.state = this.state;
export default parser;
this.parsed = parser.parse(expression.replace(/\n/g, '\\n'));
deferred.resolve(this);
});
return deferred.promise;
}
render(svg, padding) {
svg.selectAll('g').remove();
return this.parsed.render(svg.group())
.then(result => {
var box = result.getBBox();
result.transform(Snap.matrix()
.translate(padding - box.x, padding - box.y));
svg.attr({
width: box.width + padding * 2,
height: box.height + padding * 2
});
});
}
cancel() {
this.state.cancelRender = true;
}
}
+10 -14
View File
@@ -8,6 +8,8 @@ export default class Node {
this.elements = elements || [];
this.properties = properties;
this.state = Node.state;
}
set module(mod) {
@@ -68,7 +70,7 @@ export default class Node {
result = arguments;
setTimeout(() => {
if (Node.cancelRender) {
if (this.state.cancelRender) {
deferred.reject('Render cancelled');
} else {
deferred.resolve.apply(this, result);
@@ -102,27 +104,27 @@ export default class Node {
}
startRender() {
Node.renderCounter++;
this.state.renderCounter++;
}
doneRender() {
var evt;
if (Node.maxCounter === 0) {
Node.maxCounter = Node.renderCounter;
if (this.state.maxCounter === 0) {
this.state.maxCounter = this.state.renderCounter;
}
Node.renderCounter--;
this.state.renderCounter--;
evt = document.createEvent('Event');
evt.initEvent('updateStatus', true, true);
evt.detail = {
percentage: (Node.maxCounter - Node.renderCounter) / Node.maxCounter
percentage: (this.state.maxCounter - this.state.renderCounter) / this.state.maxCounter
};
document.body.dispatchEvent(evt);
if (Node.renderCounter === 0) {
Node.maxCounter = 0;
if (this.state.renderCounter === 0) {
this.state.maxCounter = 0;
}
return this.deferredStep();
@@ -240,9 +242,3 @@ export default class Node {
});
}
};
Node.reset = () => {
Node.renderCounter = 0;
Node.maxCounter = 0;
Node.cancelRender = false;
};
+1 -7
View File
@@ -1,7 +1,5 @@
import _ from 'lodash';
var groupCounter = 1;
export default {
type: 'subexp',
@@ -33,15 +31,11 @@ export default {
}));
},
resetCounter() {
groupCounter = 1;
},
setup() {
if (_.has(this.labelMap, this.properties.capture.textValue)) {
this.label = this.labelMap[this.properties.capture.textValue];
} else {
this.label = 'group #' + (groupCounter++);
this.label = 'group #' + (this.state.groupCounter++);
}
this.regexp = this.properties.regexp;