Skip to content

Commit

Permalink
working on issue zaach#348: reconstructed the 'empty action call' det…
Browse files Browse the repository at this point in the history
…ection logic so that the Jison code itself delivers an 'empty call' to compare against. The bug in zaach#348 is most probably due to the replacements of comment start/end markers in `preprocessActionCode()` and `postprocessActionCode()` while the original comparison happens between these calls, screwing up the detection, which drives the code stripper which removes the `this.performAction.call` code. Still ho-hum, though, as I don't see this happen... Anyway, this bit of rework is necessary anyway as now we're better equipped to keep detecting empty performAction functions.
  • Loading branch information
GerHobbelt committed Mar 26, 2017
1 parent 6b8e4b8 commit 1cce8b7
Showing 1 changed file with 38 additions and 23 deletions.
61 changes: 38 additions & 23 deletions lib/jison.js
Original file line number Diff line number Diff line change
Expand Up @@ -1530,20 +1530,6 @@ generator.buildProductionActions = function buildProductionActions() {
return provideSymbolAsSourcecode(sym);
});

var actionsBaseline = [
'function parser__PerformAction(' + parameters + ') {',
'/* this == yyval */',
'var yy = this.yy;',
'',
'switch (yystate) {',
'}',
'}'
].join('\n');

// report whether there are actually any custom actions at all (or any custom actions' prep code); this
// flag will be set when the generated function is essentially *empty*:
this.actionsAreAllDefault = (actionsBaseline.replace(/\s+/g, ' ') === this.performAction.replace(/\s+/g, ' '));

this.actionsUseYYLENG = analyzeFeatureUsage(this.performAction, /\byyleng\b/g, 1);
this.actionsUseYYLINENO = analyzeFeatureUsage(this.performAction, /\byylineno\b/g, 1);
this.actionsUseYYTEXT = analyzeFeatureUsage(this.performAction, /\byytext\b/g, 1);
Expand Down Expand Up @@ -1572,6 +1558,44 @@ generator.buildProductionActions = function buildProductionActions() {
this.actionsUseYYSSTACK = analyzeFeatureUsage(this.performAction, /\byysstack\b/g, 1);
this.actionsUseYYSTACKPOINTER = analyzeFeatureUsage(this.performAction, /\byysp\b/g, 1);

this.performAction = this.performAction
.replace(/\byyerror\b/g, 'yy.parser.yyError')
.replace(/\byyerrok\b(?:\s*\(\s*\))?/g, 'yy.parser.yyErrOk()')
.replace(/\byyclearin\b(?:\s*\(\s*\))?/g, 'yy.parser.yyClearIn()');

// Now that we've completed all macro expansions, it's time to execute
// the recovery code, i.e. the postprocess:
this.performAction = postprocessActionCode(this.performAction);

// Now obtain an *EMPTY* `parser__PerformAction()` to compare against and see if all the work
// actually delivered any code that is important and needs executing.
// If not, we can discard the entire function!
//
// Since we'll recursively invoke this implementation (but with a completely different
// `this` reference!), we MUST check if we're currently already constructing such an
// 'empty call':
var actionsBaseline = '';
if (!this.__constructing_empty_PerformAction_function) {
var empty_parser = {
__constructing_empty_PerformAction_function: true,

parseParams: this.parseParams,
moduleInclude: '',
moduleInit: [],
actionInclude: '',
productions: [],
nonterminals: [],
symbols: [],
operators: [],
};
buildProductionActions.call(empty_parser);
var actionsBaseline = empty_parser.performAction;

// report whether there are actually any custom actions at all (or any custom actions' prep code); this
// flag will be set when the generated function is essentially *empty*:
this.actionsAreAllDefault = (actionsBaseline.replace(/\s+/g, ' ') === this.performAction.replace(/\s+/g, ' '));
}

if (devDebug || this.DEBUG) {
Jison.print('Optimization analysis: ', {
actionsAreAllDefault: this.actionsAreAllDefault,
Expand All @@ -1596,15 +1620,6 @@ generator.buildProductionActions = function buildProductionActions() {
});
}

this.performAction = this.performAction
.replace(/\byyerror\b/g, 'yy.parser.yyError')
.replace(/\byyerrok\b(?:\s*\(\s*\))?/g, 'yy.parser.yyErrOk()')
.replace(/\byyclearin\b(?:\s*\(\s*\))?/g, 'yy.parser.yyClearIn()');

// Now that we've completed all macro expansions, it's time to execute
// the recovery code, i.e. the postprocess:
this.performAction = postprocessActionCode(this.performAction);

// And before we leave, as a SIDE EFFECT of this call, we also fixup
// the other code chunks specified in the grammar file:
//
Expand Down

0 comments on commit 1cce8b7

Please sign in to comment.