mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-27 01:36:20 +00:00
96d4a3ecf7
Due to historical reasons, the code is in subfolder "1". With SVN removal, we place the code back and remove the annoying "1" folder.
268 lines
7.9 KiB
JavaScript
268 lines
7.9 KiB
JavaScript
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
|
|
(function(mod) {
|
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
mod(require("../../lib/codemirror"));
|
|
else if (typeof define == "function" && define.amd) // AMD
|
|
define(["../../lib/codemirror"], mod);
|
|
else // Plain browser env
|
|
mod(CodeMirror);
|
|
})(function(CodeMirror) {
|
|
"use strict";
|
|
|
|
CodeMirror.defineMode("haskell", function(_config, modeConfig) {
|
|
|
|
function switchState(source, setState, f) {
|
|
setState(f);
|
|
return f(source, setState);
|
|
}
|
|
|
|
// These should all be Unicode extended, as per the Haskell 2010 report
|
|
var smallRE = /[a-z_]/;
|
|
var largeRE = /[A-Z]/;
|
|
var digitRE = /\d/;
|
|
var hexitRE = /[0-9A-Fa-f]/;
|
|
var octitRE = /[0-7]/;
|
|
var idRE = /[a-z_A-Z0-9']/;
|
|
var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
|
|
var specialRE = /[(),;[\]`{}]/;
|
|
var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
|
|
|
|
function normal(source, setState) {
|
|
if (source.eatWhile(whiteCharRE)) {
|
|
return null;
|
|
}
|
|
|
|
var ch = source.next();
|
|
if (specialRE.test(ch)) {
|
|
if (ch == '{' && source.eat('-')) {
|
|
var t = "comment";
|
|
if (source.eat('#')) {
|
|
t = "meta";
|
|
}
|
|
return switchState(source, setState, ncomment(t, 1));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
if (ch == '\'') {
|
|
if (source.eat('\\')) {
|
|
source.next(); // should handle other escapes here
|
|
}
|
|
else {
|
|
source.next();
|
|
}
|
|
if (source.eat('\'')) {
|
|
return "string";
|
|
}
|
|
return "error";
|
|
}
|
|
|
|
if (ch == '"') {
|
|
return switchState(source, setState, stringLiteral);
|
|
}
|
|
|
|
if (largeRE.test(ch)) {
|
|
source.eatWhile(idRE);
|
|
if (source.eat('.')) {
|
|
return "qualifier";
|
|
}
|
|
return "variable-2";
|
|
}
|
|
|
|
if (smallRE.test(ch)) {
|
|
source.eatWhile(idRE);
|
|
return "variable";
|
|
}
|
|
|
|
if (digitRE.test(ch)) {
|
|
if (ch == '0') {
|
|
if (source.eat(/[xX]/)) {
|
|
source.eatWhile(hexitRE); // should require at least 1
|
|
return "integer";
|
|
}
|
|
if (source.eat(/[oO]/)) {
|
|
source.eatWhile(octitRE); // should require at least 1
|
|
return "number";
|
|
}
|
|
}
|
|
source.eatWhile(digitRE);
|
|
var t = "number";
|
|
if (source.match(/^\.\d+/)) {
|
|
t = "number";
|
|
}
|
|
if (source.eat(/[eE]/)) {
|
|
t = "number";
|
|
source.eat(/[-+]/);
|
|
source.eatWhile(digitRE); // should require at least 1
|
|
}
|
|
return t;
|
|
}
|
|
|
|
if (ch == "." && source.eat("."))
|
|
return "keyword";
|
|
|
|
if (symbolRE.test(ch)) {
|
|
if (ch == '-' && source.eat(/-/)) {
|
|
source.eatWhile(/-/);
|
|
if (!source.eat(symbolRE)) {
|
|
source.skipToEnd();
|
|
return "comment";
|
|
}
|
|
}
|
|
var t = "variable";
|
|
if (ch == ':') {
|
|
t = "variable-2";
|
|
}
|
|
source.eatWhile(symbolRE);
|
|
return t;
|
|
}
|
|
|
|
return "error";
|
|
}
|
|
|
|
function ncomment(type, nest) {
|
|
if (nest == 0) {
|
|
return normal;
|
|
}
|
|
return function(source, setState) {
|
|
var currNest = nest;
|
|
while (!source.eol()) {
|
|
var ch = source.next();
|
|
if (ch == '{' && source.eat('-')) {
|
|
++currNest;
|
|
}
|
|
else if (ch == '-' && source.eat('}')) {
|
|
--currNest;
|
|
if (currNest == 0) {
|
|
setState(normal);
|
|
return type;
|
|
}
|
|
}
|
|
}
|
|
setState(ncomment(type, currNest));
|
|
return type;
|
|
};
|
|
}
|
|
|
|
function stringLiteral(source, setState) {
|
|
while (!source.eol()) {
|
|
var ch = source.next();
|
|
if (ch == '"') {
|
|
setState(normal);
|
|
return "string";
|
|
}
|
|
if (ch == '\\') {
|
|
if (source.eol() || source.eat(whiteCharRE)) {
|
|
setState(stringGap);
|
|
return "string";
|
|
}
|
|
if (source.eat('&')) {
|
|
}
|
|
else {
|
|
source.next(); // should handle other escapes here
|
|
}
|
|
}
|
|
}
|
|
setState(normal);
|
|
return "error";
|
|
}
|
|
|
|
function stringGap(source, setState) {
|
|
if (source.eat('\\')) {
|
|
return switchState(source, setState, stringLiteral);
|
|
}
|
|
source.next();
|
|
setState(normal);
|
|
return "error";
|
|
}
|
|
|
|
|
|
var wellKnownWords = (function() {
|
|
var wkw = {};
|
|
function setType(t) {
|
|
return function () {
|
|
for (var i = 0; i < arguments.length; i++)
|
|
wkw[arguments[i]] = t;
|
|
};
|
|
}
|
|
|
|
setType("keyword")(
|
|
"case", "class", "data", "default", "deriving", "do", "else", "foreign",
|
|
"if", "import", "in", "infix", "infixl", "infixr", "instance", "let",
|
|
"module", "newtype", "of", "then", "type", "where", "_");
|
|
|
|
setType("keyword")(
|
|
"\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");
|
|
|
|
setType("builtin")(
|
|
"!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
|
|
"==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
|
|
|
|
setType("builtin")(
|
|
"Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
|
|
"False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
|
|
"IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
|
|
"Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
|
|
"ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
|
|
"String", "True");
|
|
|
|
setType("builtin")(
|
|
"abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
|
|
"asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
|
|
"compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
|
|
"cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
|
|
"elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
|
|
"enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
|
|
"flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
|
|
"foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
|
|
"fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
|
|
"getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
|
|
"isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
|
|
"lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
|
|
"mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
|
|
"minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
|
|
"otherwise", "pi", "pred", "print", "product", "properFraction",
|
|
"putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
|
|
"readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
|
|
"realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
|
|
"round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
|
|
"sequence", "sequence_", "show", "showChar", "showList", "showParen",
|
|
"showString", "shows", "showsPrec", "significand", "signum", "sin",
|
|
"sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
|
|
"tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
|
|
"toRational", "truncate", "uncurry", "undefined", "unlines", "until",
|
|
"unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
|
|
"zip3", "zipWith", "zipWith3");
|
|
|
|
var override = modeConfig.overrideKeywords;
|
|
if (override) for (var word in override) if (override.hasOwnProperty(word))
|
|
wkw[word] = override[word];
|
|
|
|
return wkw;
|
|
})();
|
|
|
|
|
|
|
|
return {
|
|
startState: function () { return { f: normal }; },
|
|
copyState: function (s) { return { f: s.f }; },
|
|
|
|
token: function(stream, state) {
|
|
var t = state.f(stream, function(s) { state.f = s; });
|
|
var w = stream.current();
|
|
return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;
|
|
},
|
|
|
|
blockCommentStart: "{-",
|
|
blockCommentEnd: "-}",
|
|
lineComment: "--"
|
|
};
|
|
|
|
});
|
|
|
|
CodeMirror.defineMIME("text/x-haskell", "haskell");
|
|
|
|
});
|