<commit_before>/**
 * 
 */
var Proteus     = require("proteus"),
    EM          = require("events").EventEmitter,
    StrScanner  = require("pstrscan"),
    Expression  = require("./Expression"),
    sysutil     = require("util"),
    PClass      = Proteus.Class,
    isRegExp    = sysutil.isRegExp,
    isArray     = sysutil.isArray,
    ExParser
;

//---------------------------------------------------------------------------
// Private
//---------------------------------------------------------------------------
/**
 * Execute the expression sequences against the supplied string scanner,
 * returning whether any expression matches at the scanner's current position
 * 
 * @method execExpressions
 * @private
 * @param scanner {StringScanner} StringScanner to use for scanning
 * @returns {boolean}
 */
function execExpressions (scanner) {
    var pos  = scanner.getPosition(),
        exps = this.expressions,
        i    = exps.length,
        exp, expName, expSeq,
        results
    ;
    
    while (i--) {
        exp = exps[i];
        expName = exp[0];
        expSeq  = exp[1];
        if ((results = expSeq.exec(scanner))) {
            /**
             * The match from the last successful expression match
             * 
             * @property match
             * @type {string}
             * @default undefined
             */
            this.match = expSeq.match;
            /**
             * Array of strings for each capture from the last successful
             * expression match
             * 
             * @property captures
             * @type {array}
             * @default undefined
             */
            this.captures = results;
            this.preExpressionEndPos = pos;
            /**
             * Fired when an expression is found
             * 
             * @event preExpression
             * @param {object} the ExpressionParser instance
             * @param {string} the pre expression text
             */
            this.emit("preExpression", this.getPreExpression(), this);
            /**
             * Fired when an expression is found
             * 
             * @event *
             * @param {object} the ExpressionParser instance
             * @param {array[string]} the captures from the expression match
             */
            this.emit(expName, results, this);
            this.preExpressionStartPos = scanner.getPosition();
            return true;
        }
    }
    
    return false;
}

//---------------------------------------------------------------------------
// Public/Exports
//---------------------------------------------------------------------------
module.exports = ExParser = PClass.derive({
    
    self: {
        /**
         * Reference to our Expression Sequence utility class.
         * 
         * @property Expression
         * @type {function}
         * @static
         */
        Expression: Expression
    },
    
    /**
     * @method init
     * @param opts {object}
     *      @param expressions {array[string, String|RegExp|Expression...]}
     *      @param handlers {object} expression-name/function
     */
    init: function (opts) {
        var self, exps, evts;
        
        if (opts) {
            self = (exps = opts.expressions) && this.addExpressions(exps);
            self = (evts = opts.handlers) && this.addHandlers(evts);
        }
    },
    /**
     * Parse the supplied source string for defined expression sequences,
     * firing off the handler event for that expression as it parses.
     * 
     * @method parse
     * @param source {string|StringScanner} the string to parse
     * @returns {object} ExpressionParser instance
     */
    parse: function (src) {
        var scanner, pivotPattern, pos, matchLen;
        /**
         * The interal StringScanner instance used to traverse the string
         * 
         * @property scanner
         * @type {StringScanner}
         * @default undefined
         */
        scanner = (
            this.scanner = typeof src.scan === "function" ?
                src :
                new StrScanner(src)
        );
        /**
         * The position after the last expression match
         * 
         * @property preExpressionStartPos
         * @type {integer}
         * @default 0
         */
        /**<commit_msg>make sure we have a pstrscan instance<commit_after>/**
 * 
 */
var Proteus     = require("proteus"),
    EM          = require("events").EventEmitter,
    StrScanner  = require("pstrscan"),
    Expression  = require("./Expression"),
    sysutil     = require("util"),
    PClass      = Proteus.Class,
    isRegExp    = sysutil.isRegExp,
    isArray     = sysutil.isArray,
    ExParser
;

//---------------------------------------------------------------------------
// Private
//---------------------------------------------------------------------------
/**
 * Execute the expression sequences against the supplied string scanner,
 * returning whether any expression matches at the scanner's current position
 * 
 * @method execExpressions
 * @private
 * @param scanner {StringScanner} StringScanner to use for scanning
 * @returns {boolean}
 */
function execExpressions (scanner) {
    var pos  = scanner.getPosition(),
        exps = this.expressions,
        i    = exps.length,
        exp, expName, expSeq,
        results
    ;
    
    while (i--) {
        exp = exps[i];
        expName = exp[0];
        expSeq  = exp[1];
        if ((results = expSeq.exec(scanner))) {
            /**
             * The match from the last successful expression match
             * 
             * @property match
             * @type {string}
             * @default undefined
             */
            this.match = expSeq.match;
            /**
             * Array of strings for each capture from the last successful
             * expression match
             * 
             * @property captures
             * @type {array}
             * @default undefined
             */
            this.captures = results;
            this.preExpressionEndPos = pos;
            /**
             * Fired when an expression is found
             * 
             * @event preExpression
             * @param {object} the ExpressionParser instance
             * @param {string} the pre expression text
             */
            this.emit("preExpression", this.getPreExpression(), this);
            /**
             * Fired when an expression is found
             * 
             * @event *
             * @param {object} the ExpressionParser instance
             * @param {array[string]} the captures from the expression match
             */
            this.emit(expName, results, this);
            this.preExpressionStartPos = scanner.getPosition();
            return true;
        }
    }
    
    return false;
}

//---------------------------------------------------------------------------
// Public/Exports
//---------------------------------------------------------------------------
module.exports = ExParser = PClass.derive({
    
    self: {
        /**
         * Reference to our Expression Sequence utility class.
         * 
         * @property Expression
         * @type {function}
         * @static
         */
        Expression: Expression
    },
    
    /**
     * @method init
     * @param opts {object}
     *      @param expressions {array[string, String|RegExp|Expression...]}
     *      @param handlers {object} expression-name/function
     */
    init: function (opts) {
        var self, exps, evts;
        
        if (opts) {
            self = (exps = opts.expressions) && this.addExpressions(exps);
            self = (evts = opts.handlers) && this.addHandlers(evts);
        }
    },
    /**
     * Parse the supplied source string for defined expression sequences,
     * firing off the handler event for that expression as it parses.
     * 
     * @method parse
     * @param source {string|StringScanner} the string to parse
     * @returns {object} ExpressionParser instance
     */
    parse: function (src) {
        var scanner, pivotPattern, pos, matchLen;
        /**
         * The interal StringScanner instance used to traverse the string
         * 
         * @property scanner
         * @type {StringScanner}
         * @default undefined
         */
        scanner = (
            this.scanner = typeof src.scan === "function" ?
                // make sure we have a pstrscan instance
                src.setPosition ? src : new StrScanner(src.getSource()) :
                new StrScanner(src)
        );
        /**
         * The position after the last expression match
         * 
         * @property preExpressionStartPos
         * @type {integer}
         * @default 0
         */
        /**
{'fraction_non_alphanumeric': 0.16175634171311568, 'fraction_numerical': 0.0006825162097599818, 'mean_word_length': 1.314902580305424, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6017913', 'n_tokens_mistral': 2144, 'n_tokens_neox': 2092, 'n_words': 600}