incr-regex-package
Version:
An incremental regular expression parser in JavaScript; useful for input validation, RegExp
277 lines (231 loc) • 8.06 kB
JavaScript
/**
* Copyright (c) 2016, Nurul Choudhury
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
//
"use strict";
// import {gtPrec,sprefix,rprefix,shead,stail,sRightMerge,
// stringToList, listToArray, listToString, StackDedup, n_cons,
// n_head, n_tail, n_filter, n_reduce, n_map, n_concat,
// n_removeAll, flatten,arr_push , arr_uniq } from "./utils";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.IREGEX = exports.isOptional = exports.isMeta = exports.convertMask = 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; }; }();
var _regexUtils = require("./regex-utils");
Object.defineProperty(exports, "convertMask", {
enumerable: true,
get: function get() {
return _regexUtils.convertMask;
}
});
Object.defineProperty(exports, "isMeta", {
enumerable: true,
get: function get() {
return _regexUtils.isMeta;
}
});
Object.defineProperty(exports, "isOptional", {
enumerable: true,
get: function get() {
return _regexUtils.isOptional;
}
});
exports.incrRegEx = incrRegEx;
var _utils = require("./utils");
var _rxtree = require("./rxtree");
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
//import {RxParser} from './regexp-parser';
function isLowerCase(ch) {
var code = ch.charCodeAt(0);
return code >= 97 && code <= 122;
}
// New Regexp
/**
*
*/
var IREGEX = exports.IREGEX = function (_BaseIncRegEx) {
_inherits(IREGEX, _BaseIncRegEx);
function IREGEX() {
_classCallCheck(this, IREGEX);
return _possibleConstructorReturn(this, (IREGEX.__proto__ || Object.getPrototypeOf(IREGEX)).apply(this, arguments));
}
_createClass(IREGEX, [{
key: "toString",
/**
* [toString description]
* @return {[type]} [description]
*/
value: function toString() {
return this.str;
} /* public */
/**
* [getInputLength description]
* @return {[type]} [description]
*/
}, {
key: "getInputLength",
value: function getInputLength() {
return this.tracker.length;
}
/**
* [isDone description]
* @param {[type]} ix [description]
* @return {Boolean} [description]
*/
}, {
key: "isDone",
value: function isDone(ix) {
if (ix >= this.tracker.length || ix === undefined) {
return this.state() === _rxtree.DONE;
}
return false;
}
/**
* [getTree description]
* @return {[type]} [description]
*/
}, {
key: "getTree",
value: function getTree() {
return this.base;
} /* public */ // Get the parse tree from the regular expression
/**
* [minChars description]
* @return {[type]} [description]
*/
}, {
key: "minChars",
value: function minChars() {
/* public */ // get a ask for the regular expression from the current state of the match
this._mask = (0, _regexUtils.getArrayMask)(this.current);
return this._mask;
}
/**
* [match description]
* @param {singleCharacterString} ch the characted to match
* @return {boolean}
*/
}, {
key: "match",
value: function match(ch) {
/* public */
var fixed = (0, _rxtree.getArrayFixedAt)(this.current);
var res = this.test(ch === _rxtree.HOLDER_ANY ? undefined : ch);
if (res === undefined && ch && isLowerCase(ch)) {
res = this.test(ch.toUpperCase());
ch = ch.toUpperCase();
}
return this._update(res, ch, fixed);
}
/**
* matchStr will match as much of the input string as possible,
* return the result as rray with the following values
* [
* matchFlag : boolean - true if the entire string matched, false otherwise
* count : integer - the lenght of the substring that matched
* matchingStr : string - the substring that matched
* ]
* @param {string} str [description]
* @return {[totalMatch: boolean, howManyMatched: int32, strThatMatched: string]}
*/
}, {
key: "matchStr",
value: function matchStr(str) {
/* public */
var len = str.length;
var b1 = true,
b2 = 0; //,b3=[];
var i = 0;
for (i = 0; i < len; i++) {
var ch = str[i];
if (!this.match(ch)) {
b1 = false;break;
}
this.lastCh = ch;
b2++;
}
return [b1, b2, str.substring(0, i)];
}
/**
* [state description]
* @return {[type]} [description]
*/
}, {
key: "state",
value: function state() {
/* public */
this._state = this._state || this._stateCompute();
return this._state;
}
/**
* [stateStr description]
* @return {[type]} [description]
*/
}, {
key: "stateStr",
value: function stateStr() {
var s = this.state();
if (s === _rxtree.MORE) return "MORE"; // match is not complete but good so far
if (s === _rxtree.MAYBE) return "OK"; // match is complete but could have more
return "DONE";
}
/**
* [inputStr description]
* @return {[type]} [description]
*/
}, {
key: "inputStr",
value: function inputStr() {
return this.tracker.map(function (a) {
return a[0];
}).join('');
}
/**
* [fixed description]
* @return {[type]} [description]
*/
}, {
key: "fixed",
value: function fixed() {
return (0, _rxtree.getArrayFixedAt)(this.current);
}
/**
* [getCurrentStates description]
* @return {[type]} [description]
*/
}, {
key: "getCurrentStates",
value: function getCurrentStates() {
return this.current.map(_utils.ID);
}
}, {
key: "length",
/**
* [length description]
* @return {[type]} [description]
*/
get: function get() {
return this._len;
}
}]);
return IREGEX;
}(_regexUtils.BaseIncRegEx);
function incrRegEx(str, v) {
return new IREGEX(str, v);
}