Skip to content

Instantly share code, notes, and snippets.

@espadrine
Created June 19, 2015 11:30

Revisions

  1. espadrine created this gist Jun 19, 2015.
    1,201 changes: 1,201 additions & 0 deletions perl6.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1201 @@
    // Parts from Ace; see <https://raw.githubusercontent.com/ajaxorg/ace/master/LICENSE>
    CodeMirror.defineMode("perl6", function(cmCfg, modeCfg) {

    // Fake define() function.
    var moduleHolder = Object.create(null);

    // Given a module path as a string, create the canonical version
    // (no leading ./, no ending .js).
    var canonicalPath = function(path) {
    return path.replace(/\.\//, '').replace(/\.js$/, '');
    };

    // We intentionally add the `path` argument to `define()`.
    var define = function(path, init) {
    var exports = Object.create(null);
    init(require, exports); // module (3rd parameter) isn't supported.
    moduleHolder[canonicalPath(path)] = exports;
    };

    // path: string of the location of the JS file.
    var require = function(path) { return moduleHolder[canonicalPath(path)]; };

    // All dependencies here.
    define("../lib/oop.js", function(require, exports, module) {
    "use strict";

    exports.inherits = function(ctor, superCtor) {
    ctor.super_ = superCtor;
    ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
    value: ctor,
    enumerable: false,
    writable: true,
    configurable: true
    }
    });
    };

    exports.mixin = function(obj, mixin) {
    for (var key in mixin) {
    obj[key] = mixin[key];
    }
    return obj;
    };

    exports.implement = function(proto, mixin) {
    exports.mixin(proto, mixin);
    };

    });


    define("../lib/lang.js", function(require, exports, module) {
    "use strict";

    exports.last = function(a) {
    return a[a.length - 1];
    };

    exports.stringReverse = function(string) {
    return string.split("").reverse().join("");
    };

    exports.stringRepeat = function (string, count) {
    var result = '';
    while (count > 0) {
    if (count & 1)
    result += string;

    if (count >>= 1)
    string += string;
    }
    return result;
    };

    var trimBeginRegexp = /^\s\s*/;
    var trimEndRegexp = /\s\s*$/;

    exports.stringTrimLeft = function (string) {
    return string.replace(trimBeginRegexp, '');
    };

    exports.stringTrimRight = function (string) {
    return string.replace(trimEndRegexp, '');
    };

    exports.copyObject = function(obj) {
    var copy = {};
    for (var key in obj) {
    copy[key] = obj[key];
    }
    return copy;
    };

    exports.copyArray = function(array){
    var copy = [];
    for (var i=0, l=array.length; i<l; i++) {
    if (array[i] && typeof array[i] == "object")
    copy[i] = this.copyObject( array[i] );
    else
    copy[i] = array[i];
    }
    return copy;
    };

    exports.deepCopy = function deepCopy(obj) {
    if (typeof obj !== "object" || !obj)
    return obj;
    var copy;
    if (Array.isArray(obj)) {
    copy = [];
    for (var key = 0; key < obj.length; key++) {
    copy[key] = deepCopy(obj[key]);
    }
    return copy;
    }
    var cons = obj.constructor;
    if (cons === RegExp)
    return obj;

    copy = cons();
    for (var key in obj) {
    copy[key] = deepCopy(obj[key]);
    }
    return copy;
    };

    exports.arrayToMap = function(arr) {
    var map = {};
    for (var i=0; i<arr.length; i++) {
    map[arr[i]] = 1;
    }
    return map;

    };

    exports.createMap = function(props) {
    var map = Object.create(null);
    for (var i in props) {
    map[i] = props[i];
    }
    return map;
    };

    /*
    * splice out of 'array' anything that === 'value'
    */
    exports.arrayRemove = function(array, value) {
    for (var i = 0; i <= array.length; i++) {
    if (value === array[i]) {
    array.splice(i, 1);
    }
    }
    };

    exports.escapeRegExp = function(str) {
    return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
    };

    exports.escapeHTML = function(str) {
    return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
    };

    exports.getMatchOffsets = function(string, regExp) {
    var matches = [];

    string.replace(regExp, function(str) {
    matches.push({
    offset: arguments[arguments.length-2],
    length: str.length
    });
    });

    return matches;
    };

    /* deprecated */
    exports.deferredCall = function(fcn) {
    var timer = null;
    var callback = function() {
    timer = null;
    fcn();
    };

    var deferred = function(timeout) {
    deferred.cancel();
    timer = setTimeout(callback, timeout || 0);
    return deferred;
    };

    deferred.schedule = deferred;

    deferred.call = function() {
    this.cancel();
    fcn();
    return deferred;
    };

    deferred.cancel = function() {
    clearTimeout(timer);
    timer = null;
    return deferred;
    };

    deferred.isPending = function() {
    return timer;
    };

    return deferred;
    };


    exports.delayedCall = function(fcn, defaultTimeout) {
    var timer = null;
    var callback = function() {
    timer = null;
    fcn();
    };

    var _self = function(timeout) {
    if (timer == null)
    timer = setTimeout(callback, timeout || defaultTimeout);
    };

    _self.delay = function(timeout) {
    timer && clearTimeout(timer);
    timer = setTimeout(callback, timeout || defaultTimeout);
    };
    _self.schedule = _self;

    _self.call = function() {
    this.cancel();
    fcn();
    };

    _self.cancel = function() {
    timer && clearTimeout(timer);
    timer = null;
    };

    _self.isPending = function() {
    return timer;
    };

    return _self;
    };
    });


    define("./text_highlight_rules.js", function(require, exports, module) {
    "use strict";

    var lang = require("../lib/lang");

    var TextHighlightRules = function() {

    // regexp must not have capturing parentheses
    // regexps are ordered -> the first match is used

    this.$rules = {
    "start" : [{
    token : "empty_line",
    regex : '^$'
    }, {
    defaultToken : "text"
    }]
    };
    };

    (function() {

    this.addRules = function(rules, prefix) {
    if (!prefix) {
    for (var key in rules)
    this.$rules[key] = rules[key];
    return;
    }
    for (var key in rules) {
    var state = rules[key];
    for (var i = 0; i < state.length; i++) {
    var rule = state[i];
    if (rule.next || rule.onMatch) {
    if (typeof rule.next != "string") {
    if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
    rule.nextState = prefix + rule.nextState;
    } else {
    if (rule.next.indexOf(prefix) !== 0)
    rule.next = prefix + rule.next;
    }
    }
    }
    this.$rules[prefix + key] = state;
    }
    };

    this.getRules = function() {
    return this.$rules;
    };

    this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) {
    var embedRules = typeof HighlightRules == "function"
    ? new HighlightRules().getRules()
    : HighlightRules;
    if (states) {
    for (var i = 0; i < states.length; i++)
    states[i] = prefix + states[i];
    } else {
    states = [];
    for (var key in embedRules)
    states.push(prefix + key);
    }

    this.addRules(embedRules, prefix);

    if (escapeRules) {
    var addRules = Array.prototype[append ? "push" : "unshift"];
    for (var i = 0; i < states.length; i++)
    addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
    }

    if (!this.$embeds)
    this.$embeds = [];
    this.$embeds.push(prefix);
    };

    this.getEmbeds = function() {
    return this.$embeds;
    };

    var pushState = function(currentState, stack) {
    if (currentState != "start" || stack.length)
    stack.unshift(this.nextState, currentState);
    return this.nextState;
    };
    var popState = function(currentState, stack) {
    // if (stack[0] === currentState)
    stack.shift();
    return stack.shift() || "start";
    };

    this.normalizeRules = function() {
    var id = 0;
    var rules = this.$rules;
    function processState(key) {
    var state = rules[key];
    state.processed = true;
    for (var i = 0; i < state.length; i++) {
    var rule = state[i];
    if (!rule.regex && rule.start) {
    rule.regex = rule.start;
    if (!rule.next)
    rule.next = [];
    rule.next.push({
    defaultToken: rule.token
    }, {
    token: rule.token + ".end",
    regex: rule.end || rule.start,
    next: "pop"
    });
    rule.token = rule.token + ".start";
    rule.push = true;
    }
    var next = rule.next || rule.push;
    if (next && Array.isArray(next)) {
    var stateName = rule.stateName;
    if (!stateName) {
    stateName = rule.token;
    if (typeof stateName != "string")
    stateName = stateName[0] || "";
    if (rules[stateName])
    stateName += id++;
    }
    rules[stateName] = next;
    rule.next = stateName;
    processState(stateName);
    } else if (next == "pop") {
    rule.next = popState;
    }

    if (rule.push) {
    rule.nextState = rule.next || rule.push;
    rule.next = pushState;
    delete rule.push;
    }

    if (rule.rules) {
    for (var r in rule.rules) {
    if (rules[r]) {
    if (rules[r].push)
    rules[r].push.apply(rules[r], rule.rules[r]);
    } else {
    rules[r] = rule.rules[r];
    }
    }
    }
    if (rule.include || typeof rule == "string") {
    var includeName = rule.include || rule;
    var toInsert = rules[includeName];
    } else if (Array.isArray(rule))
    toInsert = rule;

    if (toInsert) {
    var args = [i, 1].concat(toInsert);
    if (rule.noEscape)
    args = args.filter(function(x) {return !x.next;});
    state.splice.apply(state, args);
    // skip included rules since they are already processed
    //i += args.length - 3;
    i--;
    toInsert = null;
    }

    if (rule.keywordMap) {
    rule.token = this.createKeywordMapper(
    rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive
    );
    delete rule.defaultToken;
    }
    }
    }
    Object.keys(rules).forEach(processState, this);
    };

    this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) {
    var keywords = Object.create(null);
    Object.keys(map).forEach(function(className) {
    var a = map[className];
    if (ignoreCase)
    a = a.toLowerCase();
    var list = a.split(splitChar || "|");
    for (var i = list.length; i--; )
    keywords[list[i]] = className;
    });
    // in old versions of opera keywords["__proto__"] sets prototype
    // even on objects with __proto__=null
    if (Object.getPrototypeOf(keywords)) {
    keywords.__proto__ = null;
    }
    this.$keywordList = Object.keys(keywords);
    map = null;
    return ignoreCase
    ? function(value) {return keywords[value.toLowerCase()] || defaultToken }
    : function(value) {return keywords[value] || defaultToken };
    };

    this.getKeywords = function() {
    return this.$keywords;
    };

    }).call(TextHighlightRules.prototype);

    exports.TextHighlightRules = TextHighlightRules;
    });


    define("perl_6_highlight_rules", function(require, exports, module) {
    "use strict";

    var oop = require("../lib/oop");
    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

    var Perl6HighlightRules = function() {
    // regexp must not have capturing parentheses. Use (?:) instead.
    // regexps are ordered -> the first match is used

    this.$rules = {
    start: [{
    token: "comment.block.perl",
    regex: /^=begin/,
    push: [{
    token: "comment.block.perl",
    regex: /^=end/,
    next: "pop"
    }, {
    defaultToken: "comment.block.perl"
    }]
    }, {
    token: "punctuation.definition.comment.perl",
    regex: /#/,
    push: [{
    token: "comment.line.number-sign.perl",
    regex: /$/,
    next: "pop"
    }, {
    defaultToken: "comment.line.number-sign.perl"
    }]
    }, {
    token: "punctuation.definition.string.begin.perl",
    regex: /'/,
    push: [{
    token: "punctuation.definition.string.end.perl",
    regex: /'/,
    next: "pop"
    }, {
    token: "constant.character.escape.perl",
    regex: /\\['\\]/
    }, {
    defaultToken: "string.quoted.single.perl"
    }]
    }, {
    token: "punctuation.definition.string.begin.perl",
    regex: /"/,
    push: [{
    token: "punctuation.definition.string.end.perl",
    regex: /"/,
    next: "pop"
    }, {
    token: "constant.character.escape.perl",
    regex: /\\[abtnfre"\\]/
    }, {
    defaultToken: "string.quoted.double.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.perl",
    regex: /q(?:q|to|heredoc)*\s*:?(?:q|to|heredoc)*\s*\/.+\//,
    push: [{
    token: "string.quoted.single.heredoc.perl",
    regex: /.+/,
    next: "pop"
    }, {
    defaultToken: "string.quoted.single.heredoc.perl"
    }]
    }, {
    token: "string.quoted.double.heredoc.brace.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*{{/,
    push: [{
    token: "string.quoted.double.heredoc.brace.perl",
    regex: /}}/,
    next: "pop"
    }, {
    include: "#qq_brace_string_content"
    }, {
    defaultToken: "string.quoted.double.heredoc.brace.perl"
    }]
    }, {
    token: "string.quoted.double.heredoc.paren.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*\(\(/,
    push: [{
    token: "string.quoted.double.heredoc.paren.perl",
    regex: /\)\)/,
    next: "pop"
    }, {
    include: "#qq_paren_string_content"
    }, {
    defaultToken: "string.quoted.double.heredoc.paren.perl"
    }]
    }, {
    token: "string.quoted.double.heredoc.bracket.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*\[\[/,
    push: [{
    token: "string.quoted.double.heredoc.bracket.perl",
    regex: /\]\]/,
    next: "pop"
    }, {
    include: "#qq_bracket_string_content"
    }, {
    defaultToken: "string.quoted.double.heredoc.bracket.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.brace.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*{/,
    push: [{
    token: "string.quoted.single.heredoc.brace.perl",
    regex: /}/,
    next: "pop"
    }, {
    include: "#qq_brace_string_content"
    }, {
    defaultToken: "string.quoted.single.heredoc.brace.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.slash.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*\//,
    push: [{
    token: "string.quoted.single.heredoc.slash.perl",
    regex: /\//,
    next: "pop"
    }, {
    include: "#qq_slash_string_content"
    }, {
    defaultToken: "string.quoted.single.heredoc.slash.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.paren.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*\(/,
    push: [{
    token: "string.quoted.single.heredoc.paren.perl",
    regex: /\)/,
    next: "pop"
    }, {
    include: "#qq_paren_string_content"
    }, {
    defaultToken: "string.quoted.single.heredoc.paren.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.bracket.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*\[/,
    push: [{
    token: "string.quoted.single.heredoc.bracket.perl",
    regex: /\]/,
    next: "pop"
    }, {
    include: "#qq_bracket_string_content"
    }, {
    defaultToken: "string.quoted.single.heredoc.bracket.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.single.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*'/,
    push: [{
    token: "string.quoted.single.heredoc.single.perl",
    regex: /'/,
    next: "pop"
    }, {
    include: "#qq_single_string_content"
    }, {
    defaultToken: "string.quoted.single.heredoc.single.perl"
    }]
    }, {
    token: "string.quoted.single.heredoc.double.perl",
    regex: /(?:q|Q)(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*:?(?:x|exec|w|words|ww|quotewords|v|val|q|single|qq|double|s|scalar|a|array|h|hash|f|function|c|closure|b|blackslash|regexp|substr|trans|codes|p|path)*\s*"/,
    push: [{
    token: "string.quoted.single.heredoc.double.perl",
    regex: /"/,
    next: "pop"
    }, {
    include: "#qq_double_string_content"
    }, {
    defaultToken: "string.quoted.single.heredoc.double.perl"
    }]
    }, {
    token: "variable.other.perl",
    regex: /\b\$\w+\b/
    }, {
    token: "storage.type.declare.routine.perl",
    regex: /\b(?:macro|sub|submethod|method|multi|proto|only|rule|token|regex|category)\b/
    }, {
    token: "keyword.other.module.perl",
    regex: /\b(?:module|class|role|package|enum|grammar|slang|subset)\b/
    }, {
    token: "variable.language.perl",
    regex: /\bself\b/
    }, {
    token: "keyword.other.include.perl",
    regex: /\b(?:use|require)\b/
    }, {
    token: "keyword.control.conditional.perl",
    regex: /\b(?:if|else|elsif|unless)\b/
    }, {
    token: "storage.type.variable.perl",
    regex: /\b(?:let|my|our|state|temp|has|constant)\b/
    }, {
    token: "keyword.control.repeat.perl",
    regex: /\b(?:for|loop|repeat|while|until|gather|given)\b/
    }, {
    token: "keyword.control.flowcontrol.perl",
    regex: /\b(?:take|do|when|next|last|redo|return|contend|maybe|defer|default|exit|make|continue|break|goto|leave|async|lift)\b/
    }, {
    token: "storage.modifier.type.constraints.perl",
    regex: /\b(?:is|as|but|trusts|of|returns|handles|where|augment|supersede)\b/
    }, {
    token: "meta.function.perl",
    regex: /\b(?:BEGIN|CHECK|INIT|START|FIRST|ENTER|LEAVE|KEEP|UNDO|NEXT|LAST|PRE|POST|END|CATCH|CONTROL|TEMP)\b/
    }, {
    token: "keyword.control.control-handlers.perl",
    regex: /\b(?:die|fail|try|warn)\b/
    }, {
    token: "storage.modifier.perl",
    regex: /\b(?:prec|irs|ofs|ors|export|deep|binary|unary|reparsed|rw|parsed|cached|readonly|defequiv|will|ref|copy|inline|tighter|looser|equiv|assoc|required)\b/
    }, {
    token: "constant.numeric.perl",
    regex: /\b(?:NaN|Inf)\b/
    }, {
    token: "keyword.other.pragma.perl",
    regex: /\b(?:oo|fatal)\b/
    }, {
    token: "support.type.perl",
    regex: /\b(?:Object|Any|Junction|Whatever|Capture|MatchSignature|Proxy|Matcher|Package|Module|ClassGrammar|Scalar|Array|Hash|KeyHash|KeySet|KeyBagPair|List|Seq|Range|Set|Bag|Mapping|Void|UndefFailure|Exception|Code|Block|Routine|Sub|MacroMethod|Submethod|Regex|Str|str|Blob|Char|ByteCodepoint|Grapheme|StrPos|StrLen|Version|NumComplex|num|complex|Bit|bit|bool|True|FalseIncreasing|Decreasing|Ordered|Callable|AnyCharPositional|Associative|Ordering|KeyExtractorComparator|OrderingPair|IO|KitchenSink|RoleInt|int|int1|int2|int4|int8|int16|int32|int64Rat|rat|rat1|rat2|rat4|rat8|rat16|rat32|rat64Buf|buf|buf1|buf2|buf4|buf8|buf16|buf32|buf64UInt|uint|uint1|uint2|uint4|uint8|uint16|uint32uint64|Abstraction|utf8|utf16|utf32)\b/
    }, {
    token: "keyword.operator.perl",
    regex: /\b(?:div|x|xx|mod|also|leg|cmp|before|after|eq|ne|le|lt|gt|ge|eqv|ff|fff|and|andthen|Z|X|or|xor|orelse|extra|m|mm|rx|s|tr)\b/
    }, {
    token: "variable.other.basic.perl",
    regex: /(?:\$|@|%|&)(?:\*|:|!|\^|~|=|\?|<(?=.+>))?[A-Za-z_](?:[A-Za-z0-9_]|[\-'][A-Za-z0-9_])*/
    }, {
    token: "support.function.perl",
    regex: /\b(?:eager|hyper|substr|index|rindex|grep|map|sort|join|lines|hints|chmod|split|reduce|min|max|reverse|truncate|zip|cat|roundrobin|classify|first|sum|keys|values|pairs|defined|delete|exists|elems|end|kv|any|all|one|wrap|shape|key|value|name|pop|push|shift|splice|unshift|floor|ceiling|abs|exp|log|log10|rand|sign|sqrt|sin|cos|tan|round|strand|roots|cis|unpolar|polar|atan2|pick|chop|p5chop|chomp|p5chomp|lc|lcfirst|uc|ucfirst|capitalize|normalize|pack|unpack|quotemeta|comb|samecase|sameaccent|chars|nfd|nfc|nfkd|nfkc|printf|sprintf|caller|evalfile|run|runinstead|nothing|want|bless|chr|ord|gmtime|time|eof|localtime|gethost|getpw|chroot|getlogin|getpeername|kill|fork|wait|perl|graphs|codes|bytes|clone|print|open|read|write|readline|say|seek|close|opendir|readdir|slurp|spurt|shell|run|pos|fmt|vec|link|unlink|symlink|uniq|pair|asin|atan|sec|cosec|cotan|asec|acosec|acotan|sinh|cosh|tanh|asinh|done|acos|acosh|atanh|sech|cosech|cotanh|sech|acosech|acotanh|asech|ok|nok|plan_ok|dies_ok|lives_ok|skip|todo|pass|flunk|force_todo|use_ok|isa_ok|diag|is_deeply|isnt|like|skip_rest|unlike|cmp_ok|eval_dies_ok|nok_error|eval_lives_ok|approx|is_approx|throws_ok|version_lt|plan|EVAL|succ|pred|times|nonce|once|signature|new|connect|operator|undef|undefine|sleep|from|to|infix|postfix|prefix|circumfix|postcircumfix|minmax|lazy|count|unwrap|getc|pi|e|context|void|quasi|body|each|contains|rewinddir|subst|can|isa|flush|arity|assuming|rewind|callwith|callsame|nextwith|nextsame|attr|eval_elsewhere|none|srand|trim|trim_start|trim_end|lastcall|WHAT|WHERE|HOW|WHICH|VAR|WHO|WHENCE|ACCEPTS|REJECTS|not|true|iterator|by|re|im|invert|flip|gist|flat|tree|is-prime|throws_like|trans)\b/
    }],
    "#qq_brace_string_content": [{
    token: "text",
    regex: /{/,
    push: [{
    token: "text",
    regex: /}/,
    next: "pop"
    }, {
    include: "#qq_brace_string_content"
    }]
    }],
    "#qq_bracket_string_content": [{
    token: "text",
    regex: /\[/,
    push: [{
    token: "text",
    regex: /\]/,
    next: "pop"
    }, {
    include: "#qq_bracket_string_content"
    }]
    }],
    "#qq_double_string_content": [{
    token: "text",
    regex: /"/,
    push: [{
    token: "text",
    regex: /"/,
    next: "pop"
    }, {
    include: "#qq_double_string_content"
    }]
    }],
    "#qq_paren_string_content": [{
    token: "text",
    regex: /\(/,
    push: [{
    token: "text",
    regex: /\)/,
    next: "pop"
    }, {
    include: "#qq_paren_string_content"
    }]
    }],
    "#qq_single_string_content": [{
    token: "text",
    regex: /'/,
    push: [{
    token: "text",
    regex: /'/,
    next: "pop"
    }, {
    include: "#qq_single_string_content"
    }]
    }],
    "#qq_slash_string_content": [{
    token: "text",
    regex: /\\\//,
    push: [{
    token: "text",
    regex: /\\\//,
    next: "pop"
    }, {
    include: "#qq_slash_string_content"
    }]
    }]
    }

    this.normalizeRules();
    };

    Perl6HighlightRules.metaData = {
    fileTypes: ["p6", "pl6", "pm6", "nqp"],
    firstLineMatch: "(^#!.*\\bperl6\\b)|use\\s+v6",
    keyEquivalent: "^~P",
    name: "Perl 6",
    scopeName: "source.perl.6"
    }


    oop.inherits(Perl6HighlightRules, TextHighlightRules);

    exports.Perl6HighlightRules = Perl6HighlightRules;
    });


    // Ace highlight rules function imported below.
    var HighlightRules = require("perl_6_highlight_rules").Perl6HighlightRules;



    // Ace's Syntax Tokenizer.

    // tokenizing lines longer than this makes editor very slow
    var MAX_TOKEN_COUNT = 1000;
    var Tokenizer = function(rules) {
    this.states = rules;

    this.regExps = {};
    this.matchMappings = {};
    for (var key in this.states) {
    var state = this.states[key];
    var ruleRegExps = [];
    var matchTotal = 0;
    var mapping = this.matchMappings[key] = {defaultToken: "text"};
    var flag = "g";

    var splitterRurles = [];
    for (var i = 0; i < state.length; i++) {
    var rule = state[i];
    if (rule.defaultToken)
    mapping.defaultToken = rule.defaultToken;
    if (rule.caseInsensitive)
    flag = "gi";
    if (rule.regex == null)
    continue;

    if (rule.regex instanceof RegExp)
    rule.regex = rule.regex.toString().slice(1, -1);

    // Count number of matching groups. 2 extra groups from the full match
    // And the catch-all on the end (used to force a match);
    var adjustedregex = rule.regex;
    var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2;
    if (Array.isArray(rule.token)) {
    if (rule.token.length == 1 || matchcount == 1) {
    rule.token = rule.token[0];
    } else if (matchcount - 1 != rule.token.length) {
    throw new Error("number of classes and regexp groups in '" +
    rule.token + "'\n'" + rule.regex + "' doesn't match\n"
    + (matchcount - 1) + "!=" + rule.token.length);
    } else {
    rule.tokenArray = rule.token;
    rule.token = null;
    rule.onMatch = this.$arrayTokens;
    }
    } else if (typeof rule.token == "function" && !rule.onMatch) {
    if (matchcount > 1)
    rule.onMatch = this.$applyToken;
    else
    rule.onMatch = rule.token;
    }

    if (matchcount > 1) {
    if (/\\\d/.test(rule.regex)) {
    // Replace any backreferences and offset appropriately.
    adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) {
    return "\\" + (parseInt(digit, 10) + matchTotal + 1);
    });
    } else {
    matchcount = 1;
    adjustedregex = this.removeCapturingGroups(rule.regex);
    }
    if (!rule.splitRegex && typeof rule.token != "string")
    splitterRurles.push(rule); // flag will be known only at the very end
    }

    mapping[matchTotal] = i;
    matchTotal += matchcount;

    ruleRegExps.push(adjustedregex);

    // makes property access faster
    if (!rule.onMatch)
    rule.onMatch = null;
    }

    splitterRurles.forEach(function(rule) {
    rule.splitRegex = this.createSplitterRegexp(rule.regex, flag);
    }, this);

    this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag);
    }
    };

    (function() {
    this.$setMaxTokenCount = function(m) {
    MAX_TOKEN_COUNT = m | 0;
    };

    this.$applyToken = function(str) {
    var values = this.splitRegex.exec(str).slice(1);
    var types = this.token.apply(this, values);

    // required for compatibility with old modes
    if (typeof types === "string")
    return [{type: types, value: str}];

    var tokens = [];
    for (var i = 0, l = types.length; i < l; i++) {
    if (values[i])
    tokens[tokens.length] = {
    type: types[i],
    value: values[i]
    };
    }
    return tokens;
    },

    this.$arrayTokens = function(str) {
    if (!str)
    return [];
    var values = this.splitRegex.exec(str);
    if (!values)
    return "text";
    var tokens = [];
    var types = this.tokenArray;
    for (var i = 0, l = types.length; i < l; i++) {
    if (values[i + 1])
    tokens[tokens.length] = {
    type: types[i],
    value: values[i + 1]
    };
    }
    return tokens;
    };

    this.removeCapturingGroups = function(src) {
    var r = src.replace(
    /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g,
    function(x, y) {return y ? "(?:" : x;}
    );
    return r;
    };

    this.createSplitterRegexp = function(src, flag) {
    if (src.indexOf("(?=") != -1) {
    var stack = 0;
    var inChClass = false;
    var lastCapture = {};
    src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function(
    m, esc, parenOpen, parenClose, square, index
    ) {
    if (inChClass) {
    inChClass = square != "]";
    } else if (square) {
    inChClass = true;
    } else if (parenClose) {
    if (stack == lastCapture.stack) {
    lastCapture.end = index+1;
    lastCapture.stack = -1;
    }
    stack--;
    } else if (parenOpen) {
    stack++;
    if (parenOpen.length != 1) {
    lastCapture.stack = stack
    lastCapture.start = index;
    }
    }
    return m;
    });

    if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end)))
    src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end);
    }
    return new RegExp(src, (flag||"").replace("g", ""));
    };

    /**
    * Returns an object containing two properties: `tokens`, which contains all the tokens; and `state`, the current state.
    * @returns {Object}
    **/
    this.getLineTokens = function(line, startState) {
    if (startState && typeof startState != "string") {
    var stack = startState.slice(0);
    startState = stack[0];
    } else
    var stack = [];

    var currentState = startState || "start";
    var state = this.states[currentState];
    if (!state) {
    currentState = "start";
    state = this.states[currentState];
    }
    var mapping = this.matchMappings[currentState];
    var re = this.regExps[currentState];
    re.lastIndex = 0;

    var match, tokens = [];
    var lastIndex = 0;

    var token = {type: null, value: ""};

    while (match = re.exec(line)) {
    var type = mapping.defaultToken;
    var rule = null;
    var value = match[0];
    var index = re.lastIndex;

    if (index - value.length > lastIndex) {
    var skipped = line.substring(lastIndex, index - value.length);
    if (token.type == type) {
    token.value += skipped;
    } else {
    if (token.type)
    tokens.push(token);
    token = {type: type, value: skipped};
    }
    }

    for (var i = 0; i < match.length-2; i++) {
    if (match[i + 1] === undefined)
    continue;

    rule = state[mapping[i]];

    if (rule.onMatch)
    type = rule.onMatch(value, currentState, stack);
    else
    type = rule.token;

    if (rule.next) {
    if (typeof rule.next == "string")
    currentState = rule.next;
    else
    currentState = rule.next(currentState, stack);

    state = this.states[currentState];
    if (!state) {
    window.console && console.error && console.error(currentState, "doesn't exist");
    currentState = "start";
    state = this.states[currentState];
    }
    mapping = this.matchMappings[currentState];
    lastIndex = index;
    re = this.regExps[currentState];
    re.lastIndex = index;
    }
    break;
    }

    if (value) {
    if (typeof type == "string") {
    if ((!rule || rule.merge !== false) && token.type === type) {
    token.value += value;
    } else {
    if (token.type)
    tokens.push(token);
    token = {type: type, value: value};
    }
    } else if (type) {
    if (token.type)
    tokens.push(token);
    token = {type: null, value: ""};
    for (var i = 0; i < type.length; i++)
    tokens.push(type[i]);
    }
    }

    if (lastIndex == line.length)
    break;

    lastIndex = index;

    if (tokens.length > MAX_TOKEN_COUNT) {
    // chrome doens't show contents of text nodes with very long text
    while (lastIndex < line.length) {
    if (token.type)
    tokens.push(token);
    token = {
    value: line.substring(lastIndex, lastIndex += 2000),
    type: "overflow"
    };
    }
    currentState = "start";
    stack = [];
    break;
    }
    }

    if (token.type)
    tokens.push(token);

    if (stack.length > 1) {
    if (stack[0] !== currentState)
    stack.unshift(currentState);
    }
    return {
    tokens : tokens,
    state : stack.length ? stack : currentState
    };
    };

    }).call(Tokenizer.prototype);

    // Token conversion.
    // See <https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode#common-tokens>
    // This is not an exact match nor the best match that can be made.
    var tokenFromAceToken = {
    empty: null,
    text: null,

    // Keyword
    keyword: 'keyword',
    control: 'keyword',
    operator: 'operator',

    // Constants
    constant: 'atom',
    numeric: 'number',
    character: 'atom',
    escape: 'atom',

    // Variables
    variable: 'variable',
    parameter: 'variable-3',
    language: 'variable-2', // Python's `self` uses that.

    // Comments
    comment: 'comment',
    line: 'comment',
    'double-slash': 'comment',
    'double-dash': 'comment',
    'number-sign': 'comment',
    percentage: 'comment',
    block: 'comment',
    documentation: 'comment',

    // String
    string: 'string',
    quoted: 'string',
    single: 'string',
    double: 'string',
    triple: 'string',
    unquoted: 'string',
    interpolated: 'string',
    regexp: 'string-2',

    meta: 'meta',
    literal: 'qualifier',
    support: 'builtin',

    // Markup
    markup: 'tag',
    underline: 'link',
    link: 'link',
    bold: 'strong',
    heading: 'header',
    italic: 'em',
    list: 'variable-2',
    numbered: 'variable-2',
    unnumbered: 'variable-2',
    quote: 'quote',
    raw: 'variable-2', // Markdown's raw block uses that.

    // Invalid
    invalid: 'error',
    illegal: 'invalidchar',
    deprecated: 'error'
    };

    // Takes a list of Ace tokens, returns a (string) CodeMirror token.
    var cmTokenFromAceTokens = function(tokens) {
    var token = null;
    for (var i = 0; i < tokens.length; i++) {
    // Find the most specific token.
    if (tokenFromAceToken[tokens[i]] !== undefined) {
    token = tokenFromAceToken[tokens[i]];
    }
    }
    return token;
    };

    // Consume a token from plannedTokens.
    var consumeToken = function(stream, state) {
    var plannedToken = state.plannedTokens.shift();
    if (plannedToken === undefined) {
    return null;
    }
    stream.match(plannedToken.value);
    var tokens = plannedToken.type.split('.');
    return cmTokenFromAceTokens(tokens);
    };

    var matchToken = function(stream, state) {
    // Anormal start: we already have planned tokens to consume.
    if (state.plannedTokens.length > 0) {
    return consumeToken(stream, state);
    }

    // Normal start.
    var currentState = state.current;
    var currentLine = stream.match(/.*$/, false)[0];
    var tokenized = tokenizer.getLineTokens(currentLine, currentState);
    // We got a {tokens, state} object.
    // Each token is a {value, type} object.
    state.plannedTokens = tokenized.tokens;
    state.current = tokenized.state;

    // Consume a token.
    return consumeToken(stream, state);
    }

    // Initialize all state.
    var aceHighlightRules = new HighlightRules();
    var tokenizer = new Tokenizer(aceHighlightRules.$rules);

    return {
    startState: function() {
    return {
    current: 'start',
    // List of {value, type}, with type being an Ace token string.
    plannedTokens: []
    };
    },
    blankLine: function(state) { matchToken('', state); },
    token: matchToken
    };
    });

    CodeMirror.defineMIME("text/x-perl6", "perl6");