syntax-cli-prog
Version:
Syntactic analysis toolkit, language agnostic parsers generator.
233 lines (182 loc) • 5.41 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _vm = require('vm');
var _vm2 = _interopRequireDefault(_vm);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var SANDBOX = Object.assign(global, {
/**
* Matched text of the tokenizer.
*/
yytext: '',
/**
* Length of the matched text.
*/
yyleng: 0,
/**
* Extra global object lex rules, and other handlers
* may use to track any needed state across the handlers.
*/
yy: {},
/**
* Stores different parse callbacks.
*/
yyparse: {
onParseBegin: function onParseBegin() {},
onParseEnd: function onParseEnd() {}
},
/**
* Creates location object.
*/
yyloc: function yyloc(start, end) {
// Epsilon doesn't produce location.
if (!start || !end) {
return start || end;
}
return {
startOffset: start.startOffset,
endOffset: end.endOffset,
startLine: start.startLine,
endLine: end.endLine,
startColumn: start.startColumn,
endColumn: end.endColumn
};
},
/**
* Result value of production handlers, used as $$.
*/
__: null,
/**
* Result node location object.
*/
__loc: null,
/**
* To require modules.
*/
require: require
});
/**
* Execution context.
*/
/**
* The MIT License (MIT)
* Copyright (c) 2015-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
var context = new _vm2.default.createContext(SANDBOX);
/**
* Evaluation unit for different handlers (of lex rules, productions, etc),
* which shares the same global space via sandbox.
*/
var CodeUnit = {
/**
* Sets value to bindings.
*/
setBindings: function setBindings(bindings) {
Object.assign(SANDBOX, bindings);
},
/**
* Evaluates the code. If `shouldRewrite` is `true` (default),
* rewrites $1, $2, $$, etc. to _1, _2, __, etc.
*/
eval: function _eval(code) {
var shouldRewrite = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (shouldRewrite) {
code = this._rewriteParamsInCode(code);
}
return _vm2.default.runInContext(code, context);
},
/**
* Creates parameters string for a semantic action.
*
* Consists of: positioned arguments, named arguments,
* and location data.
*
* Example of using the arguments in a handler:
*
* $1, $2, $expr, $term, @1, @2
*
* Created parameters: _1, _2, _expr, _term, _1loc, _2loc
*/
createProductionParamsArray: function createProductionParamsArray(_ref) {
var production = _ref.production,
captureLocations = _ref.captureLocations;
if (production.isEpsilon()) {
return [];
}
var symbols = production.getRHS().map(function (symbol) {
return symbol.getSymbol();
});
// $1, $2, ...
var semanticValues = [];
// @1, @2, ...
var locations = captureLocations ? [] : null;
for (var i = 0; i < symbols.length; i++) {
var semanticValue = '_' + (i + 1);
semanticValues.push(semanticValue);
if (captureLocations) {
locations.push(semanticValue + 'loc');
}
}
var params = captureLocations ? semanticValues.concat(locations) : semanticValues;
return params;
},
/**
* See `createProductionParamsArray`.
*/
createProductionParams: function createProductionParams(_ref2) {
var production = _ref2.production,
captureLocations = _ref2.captureLocations;
return this.createProductionParamsArray({
production: production,
captureLocations: captureLocations
}).join(', ');
},
/**
* Creates default location prologue to semantic action. Begin is
* taken from first symbol on RHS, the end -- from the last one.
*
* @$.startOffset = @1.startOffset
* @$.endOffset = @1.endOffset
* ...
*/
createLocationPrologue: function createLocationPrologue(production) {
if (production.isEpsilon()) {
return '__loc = null;';
}
var start = 1;
var end = production.getRHS().length;
return '__loc = yyloc(_' + start + 'loc, _' + end + 'loc);';
},
/**
* Creates a handler for a production. Attaches default
* location prologue (user code can override it).
*/
createProductionHandler: function createProductionHandler(_ref3) {
var production = _ref3.production,
captureLocations = _ref3.captureLocations;
var params = this.createProductionParams({ production: production, captureLocations: captureLocations });
var locationPrologue = captureLocations ? this.createLocationPrologue(production) : '';
var action = production.getRawSemanticAction();
return this.createHandler(params, locationPrologue + action);
},
/**
* Rewrites $1, @1, $name to _1, _1loc, _name
*/
_rewriteParamsInCode: function _rewriteParamsInCode(code) {
return code.replace(/\$(\d+)/g, '_$1').replace(/@(\d+)/g, '_$1loc').replace(/\$\$/g, '__').replace(/@\$/g, '__loc');
},
/**
* Creates a handler function with code, and parameters.
*/
createHandler: function createHandler(parameters, code) {
return this.eval('(function(' + parameters + ') { ' + code + ' })');
},
/**
* Returns evaluation sandbox.
*/
getSandbox: function getSandbox() {
return SANDBOX;
}
};
exports.default = CodeUnit;