UNPKG

@masala/parser

Version:
255 lines (209 loc) 8.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GenLex = exports.Token = exports.TokenDefinition = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.getMathGenLex = getMathGenLex; var _response = require("../parsec/response"); var _response2 = _interopRequireDefault(_response); var _parsec = require("../parsec"); var _unit = require("../data/unit"); var _unit2 = _interopRequireDefault(_unit); var _option = require("../data/option"); var _option2 = _interopRequireDefault(_option); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var TokenDefinition = // value will be determined at runtime while parsing exports.TokenDefinition = function TokenDefinition(parser, name, precedence) { _classCallCheck(this, TokenDefinition); this.parser = parser; this.name = name; this.precedence = precedence; }; // a Token object is instantiated at runtime, with a value given by the parsed text var Token = exports.Token = function () { function Token(name, value) { _classCallCheck(this, Token); this.name = name; this.value = value; } _createClass(Token, [{ key: "accept", value: function accept(name) { // TODO logger console.log('accepting', name, this.name===name, this.value); return this.name === name ? _option2.default.some(this.value) : _option2.default.none(); } }]); return Token; }(); var GenLex = exports.GenLex = function () { function GenLex() { _classCallCheck(this, GenLex); this.spaces = defaultSpaces(); // definitions keep trace of all: parser, precedence and name this.definitions = []; // get a token, but not directly its precedence this.tokensMap = {}; } _createClass(GenLex, [{ key: "tokenize", value: function tokenize(parser, name) { var precedence = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1000; if (typeof parser === 'string') { if (name === undefined) { name = parser; } return this.tokenize(_parsec.C.string(parser), name, precedence); } var definition = new TokenDefinition(parser, name, precedence); this.definitions.push(definition); // probably a bad name var token = literal(function (token) { return token.accept(name); }, name); this.tokensMap[name] = token; return token; } }, { key: "keywords", value: function keywords(keys) { var _this = this; var precedence = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000; return keys.reduce(function (acc, key) { return acc.concat(_this.tokenize(key, key, precedence)); }, []); } }, { key: "setSeparators", value: function setSeparators(spacesCharacters) { if (typeof spacesCharacters !== 'string') { throw "setSeparators needs a string as separators, such as ' \r\n\f\t' ;" + " use setSeparatorsParser to declare a parser"; } this.spaces = _parsec.C.charIn(spacesCharacters).map(function () { return _unit2.default; }); } /** * Set separator Parser. It's up to the parser to accept or not * optional repetition * @param spacesParser */ }, { key: "setSeparatorsParser", value: function setSeparatorsParser(spacesParser) { this.spaces = spacesParser.map(function () { return _unit2.default; }); } }, { key: "updatePrecedence", value: function updatePrecedence(tokenName, precedence) { this.definitions.find(function (def) { return def.name === tokenName; }).precedence = precedence; } }, { key: "buildTokenizer", value: function buildTokenizer() { var token = this.findTokenByPrecedence(); return this.spaces.optrep().drop().then(token).then(this.spaces.optrep().drop()).single(); } }, { key: "use", value: function use(grammar) { return this.buildTokenizer().chain(grammar); } }, { key: "findTokenByPrecedence", value: function findTokenByPrecedence() { var sortedDefinitions = this.definitions.sort(function (d1, d2) { return d2.precedence - d1.precedence; }); return sortedDefinitions.reduce(function (combinator, definition) { return _parsec.F.try(getTokenParser(definition)) // .or (F.error('no match for '+definition.name)) .or(combinator); }, _parsec.F.error()); } }, { key: "remove", value: function remove(tokenName) { // find definitions this.definitions = this.definitions.filter(function (d) { return d.name !== tokenName; }); delete this.tokensMap[tokenName]; } // type: { [key: string]: Parser } }, { key: "tokens", value: function tokens() { return this.tokensMap; } }, { key: "get", value: function get(tokenName) { return this.tokensMap[tokenName]; } }]); return GenLex; }(); function getTokenParser(def) { return def.parser.map(function (value) { return new Token(def.name, value); }); } // name is for easier debugging // eslint-disable-next-line function literal(tokenize, name) { return _parsec.F.parse(function (input, index) { // TODO logger console.log('testing ', {name, input:input.get(index), index}); // console.log('trying ', {index, name}); return input.get(index) // FIXME= value is the token, token is the value .map(function (value) { /* TODO: keep for logger let token = value; try { console.log('in map', {value, name, index}); console.log('tokenizing', tokenize(token)); } catch (e) { console.error('failed', e) }*/ return tokenize(value).map(function (token) { // TODO logger console.log('accept with ', name, index); //console.log('accept:', token,index, input.location(index)); return _response2.default.accept(token, input, index + 1, true); }).orLazyElse(function () { // TODO logger console.log('lazyElse failed with ', name, index); // console.log('reject:',index, input.source.offsets[index],input,'>>>', value, // input.location(index)); return _response2.default.reject(input, index, false); }); }).lazyRecoverWith(function () { // TODO logger console.log('failed with ', name, index); //console.log('lazyRecover with offset:', input.location(index)); return _response2.default.reject(input, index, false); }); }); } function defaultSpaces() { return _parsec.C.charIn(' \r\n\f\t').map(function () { return _unit2.default; }); } function getMathGenLex() { var basicGenlex = new GenLex(); // We try first to have digits basicGenlex.tokenize(_parsec.N.number(), 'number', 1100); basicGenlex.tokenize(_parsec.C.char('+'), 'plus', 1000); basicGenlex.tokenize(_parsec.C.char('-'), 'minus', 1000); basicGenlex.tokenize(_parsec.C.char('*'), 'mult', 800); basicGenlex.tokenize(_parsec.C.char('/'), 'div', 800); basicGenlex.tokenize(_parsec.C.char('('), 'open', 1000); basicGenlex.tokenize(_parsec.C.char(')'), 'close', 1000); return basicGenlex; } //# sourceMappingURL=genlex.js.map