jablonka.czprosek.czf

websvn

Subversion Repositories:
[/] [templates/] [calm/] [star-light/] [src/] [ParseMaster.js] - Rev 3 Go to most recent revision

Compare with Previous - Blame - Download


/*
        ParseMaster, version 1.0 (pre-release) (2005/05/12) x6
        Copyright 2005, Dean Edwards
        Web: http://dean.edwards.name/

        This software is licensed under the CC-GNU LGPL
        Web: http://creativecommons.org/licenses/LGPL/2.1/
*/

/* a multi-pattern parser */

/*    ---   (include) http://dean.edwards.name/my/fix-ie5.js       ---    */
/*    ---   (require) http://dean.edwards.name/common/common.js       ---    */

function ParseMaster() {
        // constants
        var $EXPRESSION = 0, $REPLACEMENT = 1, $LENGTH = 2;
        // used to determine nesting levels
        var $GROUPS = /\(/g, $SUB_REPLACE = /\$\d/, $INDEXED = /^\$\d+$/,
            $TRIM = /(['"])\1\+(.*)\+\1\1$/, $$ESCAPE = /\\./g, $QUOTE = /'/,
            $$DELETED = /\001[^\001]*\001/g;
        function $DELETE($match, $offset){return "\001" + $match[$offset] + "\001"};
        // public
        this.add = function($expression, $replacement) {
                if (!$replacement) $replacement = $DELETE;
                // count the number of sub-expressions
                //  - add one because each pattern is itself a sub-expression
                var $length = (_internalEscape(String($expression)).match($GROUPS) || "").length + 1;
                // does the pattern deal with sub-expressions?
                if (typeof $replacement == "string" && $SUB_REPLACE.test($replacement)) {
                        // a simple lookup? (e.g. "$2")
                        if ($INDEXED.test($replacement)) {
                                // store the index (used for fast retrieval of matched strings)
                                $replacement = parseInt($replacement.slice(1)) - 1;
                        } else { // a complicated lookup (e.g. "Hello $2 $1")
                                // build a function to do the lookup
                                var i = $length;
                                var $quote = $QUOTE.test(_internalEscape($replacement)) ? '"' : "'";
                                while (i) $replacement = $replacement.split("$" + i--).join($quote + "+a[o+" + i + "]+" + $quote);
                                $replacement = new Function("a,o", "return" + $quote + $replacement.replace($TRIM, "$1") + $quote);
                        }
                }
                // pass the modified arguments
                _add($expression || "/^$/", $replacement, $length);
        };
        // execute the global replacement
        this.exec = function($string) {
                return _unescape(_escape($string, this.escapeChar).replace(
                        new RegExp(_patterns, this.ignoreCase ? "gi" : "g"), _replacement), this.escapeChar).replace($$DELETED, "");
        };
        // clear the patterns collections so that this object may be re-used
        this.reset = function() {
                _patterns.length = 0;
        };

        // private
        var _patterns = [];   // patterns stored by index
        var _toString = function(){return "(" + String(this[$EXPRESSION]).slice(1, -1) + ")"};
        _patterns.toString = function(){return this.join("|")};
        // create and add a new pattern to the patterns collection
        function _add() {
                arguments.toString = _toString;
                // store the pattern - as an arguments object (i think this is quicker..?)
                _patterns[_patterns.length] = arguments;
        }
        // this is the global replace function (it's quite complicated)
        function _replacement() {
                if (!arguments[0]) return "";
                var i = 1, j = 0, $pattern;
                // loop through the patterns
                while ($pattern = _patterns[j++]) {
                        // do we have a result?
                        if (arguments[i]) {
                                var $replacement = $pattern[$REPLACEMENT];
                                switch (typeof $replacement) {
                                        case "function": return $replacement(arguments, i);
                                        case "number": return arguments[$replacement + i];
                                        default: return $replacement;
                                }
                        // skip over references to sub-expressions
                        } else i += $pattern[$LENGTH];
                }
        };
        // encode escaped characters
        var _escaped = [];
        function _escape($string, $escapeChar) {
                return $escapeChar ? $string.replace(new RegExp("\\" + $escapeChar + "(.)", "g"), function($match, $char) {
                        _escaped[_escaped.length] = $char;
                        return $escapeChar;
                }) : $string;
        };
        // decode escaped characters
        function _unescape($string, $escapeChar) {
                var i = 0;
                return $escapeChar ? $string.replace(new RegExp("\\" + $escapeChar, "g"), function() {
                        return $escapeChar + (_escaped[i++] || "");
                }) : $string;
        };
        function _internalEscape($string) {
                return $string.replace($$ESCAPE, "");
        };
};
Common.specialize({
        constructor: ParseMaster,
        ignoreCase: false,
        escapeChar: ""
});

Powered by WebSVN 2.2.1