moved to root
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
CodeMirror.defineMode("regex", function() {
|
||||
function characterSetTokenizer(stream, state) {
|
||||
let context = state.currentContext();
|
||||
|
||||
if (context.negatedCharacterSet === undefined) {
|
||||
context.negatedCharacterSet = stream.eat("^");
|
||||
if (context.negatedCharacterSet)
|
||||
return "regex-character-set-negate";
|
||||
}
|
||||
|
||||
while (stream.peek()) {
|
||||
if (stream.eat("\\"))
|
||||
return consumeEscapeSequence(stream);
|
||||
|
||||
if (stream.eat("]")) {
|
||||
state.tokenize = tokenBase;
|
||||
return state.popContext();
|
||||
}
|
||||
|
||||
stream.next();
|
||||
}
|
||||
|
||||
return "error";
|
||||
}
|
||||
|
||||
function consumeEscapeSequence(stream) {
|
||||
if (stream.match(/[bBdDwWsStrnvf0]/))
|
||||
return "regex-special";
|
||||
|
||||
if (stream.eat("x")) {
|
||||
if (stream.match(/[0-9a-fA-F]{2}/))
|
||||
return "regex-escape";
|
||||
return "error";
|
||||
}
|
||||
|
||||
if (stream.eat("u")) {
|
||||
if (stream.match(/[0-9a-fA-F]{4}/))
|
||||
return "regex-escape-2";
|
||||
return "error";
|
||||
}
|
||||
|
||||
if (stream.eat("c")) {
|
||||
if (stream.match(/[A-Z]/))
|
||||
return "regex-escape-3";
|
||||
return "error";
|
||||
}
|
||||
|
||||
if (stream.match(/[1-9]/))
|
||||
return "regex-backreference";
|
||||
|
||||
if (stream.next())
|
||||
return "regex-literal";
|
||||
|
||||
return "error";
|
||||
}
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
let ch = stream.next();
|
||||
|
||||
if (ch === "\\")
|
||||
return consumeEscapeSequence(stream);
|
||||
|
||||
// Match start of capturing/noncapturing group, or positive/negative lookaheads.
|
||||
if (ch === "(") {
|
||||
let style;
|
||||
if (stream.match(/\?[=!]/))
|
||||
style = "regex-lookahead";
|
||||
else {
|
||||
stream.match(/\?:/);
|
||||
style = "regex-group";
|
||||
}
|
||||
|
||||
return state.pushContext(stream, style, ")");
|
||||
}
|
||||
|
||||
let context = state.currentContext();
|
||||
if (context && context.type === ch)
|
||||
return state.popContext();
|
||||
|
||||
// Match quantifiers: *, +, ?, {n}, {n,}, and {n,m}
|
||||
if (/[*+?]/.test(ch))
|
||||
return "regex-quantifier";
|
||||
|
||||
if (ch === "{") {
|
||||
if (stream.match(/\d+}/))
|
||||
return "regex-quantifier";
|
||||
|
||||
let matches = stream.match(/(\d+),(\d+)?}/);
|
||||
if (!matches)
|
||||
return "error";
|
||||
|
||||
let minimum = parseInt(matches[1]);
|
||||
let maximum = parseInt(matches[2]);
|
||||
if (minimum > maximum)
|
||||
return "error";
|
||||
|
||||
return "regex-quantifier";
|
||||
}
|
||||
|
||||
// Match character sets.
|
||||
if (ch === "[") {
|
||||
state.tokenize = characterSetTokenizer;
|
||||
return state.pushContext(stream, "regex-character-set");
|
||||
}
|
||||
|
||||
// Match miscelleneous special characters.
|
||||
if (/[.^$|]/.test(ch))
|
||||
return "regex-special";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
let contextStack = [];
|
||||
return {
|
||||
currentContext: function() {
|
||||
return contextStack.length ? contextStack[contextStack.length - 1] : null;
|
||||
},
|
||||
pushContext: function(stream, data, type) {
|
||||
let context = {data, type};
|
||||
contextStack.push(context);
|
||||
return data;
|
||||
},
|
||||
popContext: function() {
|
||||
console.assert(contextStack.length, "Tried to pop empty context stack.");
|
||||
return contextStack.pop().data;
|
||||
},
|
||||
tokenize: tokenBase,
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-regex", "regex");
|
||||
Reference in New Issue
Block a user