dylan.js
352 lines
| 9.9 KiB
| application/javascript
|
JavascriptLexer
r1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others | |||
r4105 | // Distributed under an MIT license: https://codemirror.net/LICENSE | |||
r1 | ||||
(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"; | ||||
r4105 | function forEach(arr, f) { | |||
for (var i = 0; i < arr.length; i++) f(arr[i], i) | ||||
} | ||||
function some(arr, f) { | ||||
for (var i = 0; i < arr.length; i++) if (f(arr[i], i)) return true | ||||
return false | ||||
} | ||||
r1 | CodeMirror.defineMode("dylan", function(_config) { | |||
// Words | ||||
var words = { | ||||
// Words that introduce unnamed definitions like "define interface" | ||||
unnamedDefinition: ["interface"], | ||||
// Words that introduce simple named definitions like "define library" | ||||
namedDefinition: ["module", "library", "macro", | ||||
"C-struct", "C-union", | ||||
"C-function", "C-callable-wrapper" | ||||
], | ||||
// Words that introduce type definitions like "define class". | ||||
// These are also parameterized like "define method" and are | ||||
// appended to otherParameterizedDefinitionWords | ||||
typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"], | ||||
// Words that introduce trickier definitions like "define method". | ||||
// These require special definitions to be added to startExpressions | ||||
otherParameterizedDefinition: ["method", "function", | ||||
"C-variable", "C-address" | ||||
], | ||||
// Words that introduce module constant definitions. | ||||
// These must also be simple definitions and are | ||||
// appended to otherSimpleDefinitionWords | ||||
constantSimpleDefinition: ["constant"], | ||||
// Words that introduce module variable definitions. | ||||
// These must also be simple definitions and are | ||||
// appended to otherSimpleDefinitionWords | ||||
variableSimpleDefinition: ["variable"], | ||||
// Other words that introduce simple definitions | ||||
// (without implicit bodies). | ||||
otherSimpleDefinition: ["generic", "domain", | ||||
"C-pointer-type", | ||||
"table" | ||||
], | ||||
// Words that begin statements with implicit bodies. | ||||
statement: ["if", "block", "begin", "method", "case", | ||||
"for", "select", "when", "unless", "until", | ||||
"while", "iterate", "profiling", "dynamic-bind" | ||||
], | ||||
// Patterns that act as separators in compound statements. | ||||
// This may include any general pattern that must be indented | ||||
// specially. | ||||
separator: ["finally", "exception", "cleanup", "else", | ||||
"elseif", "afterwards" | ||||
], | ||||
// Keywords that do not require special indentation handling, | ||||
// but which should be highlighted | ||||
other: ["above", "below", "by", "from", "handler", "in", | ||||
"instance", "let", "local", "otherwise", "slot", | ||||
"subclass", "then", "to", "keyed-by", "virtual" | ||||
], | ||||
// Condition signaling function calls | ||||
signalingCalls: ["signal", "error", "cerror", | ||||
"break", "check-type", "abort" | ||||
] | ||||
}; | ||||
words["otherDefinition"] = | ||||
words["unnamedDefinition"] | ||||
.concat(words["namedDefinition"]) | ||||
.concat(words["otherParameterizedDefinition"]); | ||||
words["definition"] = | ||||
words["typeParameterizedDefinition"] | ||||
.concat(words["otherDefinition"]); | ||||
words["parameterizedDefinition"] = | ||||
words["typeParameterizedDefinition"] | ||||
.concat(words["otherParameterizedDefinition"]); | ||||
words["simpleDefinition"] = | ||||
words["constantSimpleDefinition"] | ||||
.concat(words["variableSimpleDefinition"]) | ||||
.concat(words["otherSimpleDefinition"]); | ||||
words["keyword"] = | ||||
words["statement"] | ||||
.concat(words["separator"]) | ||||
.concat(words["other"]); | ||||
// Patterns | ||||
var symbolPattern = "[-_a-zA-Z?!*@<>$%]+"; | ||||
var symbol = new RegExp("^" + symbolPattern); | ||||
var patterns = { | ||||
// Symbols with special syntax | ||||
symbolKeyword: symbolPattern + ":", | ||||
symbolClass: "<" + symbolPattern + ">", | ||||
symbolGlobal: "\\*" + symbolPattern + "\\*", | ||||
symbolConstant: "\\$" + symbolPattern | ||||
}; | ||||
var patternStyles = { | ||||
symbolKeyword: "atom", | ||||
symbolClass: "tag", | ||||
symbolGlobal: "variable-2", | ||||
symbolConstant: "variable-3" | ||||
}; | ||||
// Compile all patterns to regular expressions | ||||
for (var patternName in patterns) | ||||
if (patterns.hasOwnProperty(patternName)) | ||||
patterns[patternName] = new RegExp("^" + patterns[patternName]); | ||||
// Names beginning "with-" and "without-" are commonly | ||||
// used as statement macro | ||||
patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/]; | ||||
var styles = {}; | ||||
styles["keyword"] = "keyword"; | ||||
styles["definition"] = "def"; | ||||
styles["simpleDefinition"] = "def"; | ||||
styles["signalingCalls"] = "builtin"; | ||||
// protected words lookup table | ||||
var wordLookup = {}; | ||||
var styleLookup = {}; | ||||
r4105 | forEach([ | |||
r1 | "keyword", | |||
"definition", | ||||
"simpleDefinition", | ||||
"signalingCalls" | ||||
r4105 | ], function(type) { | |||
forEach(words[type], function(word) { | ||||
r1 | wordLookup[word] = type; | |||
styleLookup[word] = styles[type]; | ||||
}); | ||||
}); | ||||
function chain(stream, state, f) { | ||||
state.tokenize = f; | ||||
return f(stream, state); | ||||
} | ||||
function tokenBase(stream, state) { | ||||
// String | ||||
var ch = stream.peek(); | ||||
if (ch == "'" || ch == '"') { | ||||
stream.next(); | ||||
return chain(stream, state, tokenString(ch, "string")); | ||||
} | ||||
// Comment | ||||
else if (ch == "/") { | ||||
stream.next(); | ||||
if (stream.eat("*")) { | ||||
return chain(stream, state, tokenComment); | ||||
} else if (stream.eat("/")) { | ||||
stream.skipToEnd(); | ||||
return "comment"; | ||||
} | ||||
r4105 | stream.backUp(1); | |||
r1 | } | |||
// Decimal | ||||
r4105 | else if (/[+\-\d\.]/.test(ch)) { | |||
if (stream.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i) || | ||||
stream.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i) || | ||||
stream.match(/^[+-]?\d+/)) { | ||||
return "number"; | ||||
} | ||||
r1 | } | |||
// Hash | ||||
else if (ch == "#") { | ||||
stream.next(); | ||||
// Symbol with string syntax | ||||
ch = stream.peek(); | ||||
if (ch == '"') { | ||||
stream.next(); | ||||
r4105 | return chain(stream, state, tokenString('"', "string")); | |||
r1 | } | |||
// Binary number | ||||
else if (ch == "b") { | ||||
stream.next(); | ||||
stream.eatWhile(/[01]/); | ||||
return "number"; | ||||
} | ||||
// Hex number | ||||
else if (ch == "x") { | ||||
stream.next(); | ||||
stream.eatWhile(/[\da-f]/i); | ||||
return "number"; | ||||
} | ||||
// Octal number | ||||
else if (ch == "o") { | ||||
stream.next(); | ||||
stream.eatWhile(/[0-7]/); | ||||
return "number"; | ||||
} | ||||
r4105 | // Token concatenation in macros | |||
else if (ch == '#') { | ||||
stream.next(); | ||||
return "punctuation"; | ||||
} | ||||
// Sequence literals | ||||
else if ((ch == '[') || (ch == '(')) { | ||||
stream.next(); | ||||
return "bracket"; | ||||
r1 | // Hash symbol | |||
r4105 | } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) { | |||
return "atom"; | ||||
} else { | ||||
r1 | stream.eatWhile(/[-a-zA-Z]/); | |||
r4105 | return "error"; | |||
} | ||||
} else if (ch == "~") { | ||||
stream.next(); | ||||
ch = stream.peek(); | ||||
if (ch == "=") { | ||||
stream.next(); | ||||
ch = stream.peek(); | ||||
if (ch == "=") { | ||||
stream.next(); | ||||
return "operator"; | ||||
} | ||||
return "operator"; | ||||
r1 | } | |||
r4105 | return "operator"; | |||
} else if (ch == ":") { | ||||
stream.next(); | ||||
ch = stream.peek(); | ||||
if (ch == "=") { | ||||
stream.next(); | ||||
return "operator"; | ||||
} else if (ch == ":") { | ||||
stream.next(); | ||||
return "punctuation"; | ||||
} | ||||
} else if ("[](){}".indexOf(ch) != -1) { | ||||
stream.next(); | ||||
return "bracket"; | ||||
} else if (".,".indexOf(ch) != -1) { | ||||
stream.next(); | ||||
return "punctuation"; | ||||
r1 | } else if (stream.match("end")) { | |||
return "keyword"; | ||||
} | ||||
for (var name in patterns) { | ||||
if (patterns.hasOwnProperty(name)) { | ||||
var pattern = patterns[name]; | ||||
r4105 | if ((pattern instanceof Array && some(pattern, function(p) { | |||
r1 | return stream.match(p); | |||
})) || stream.match(pattern)) | ||||
return patternStyles[name]; | ||||
} | ||||
} | ||||
r4105 | if (/[+\-*\/^=<>&|]/.test(ch)) { | |||
stream.next(); | ||||
return "operator"; | ||||
} | ||||
r1 | if (stream.match("define")) { | |||
return "def"; | ||||
} else { | ||||
stream.eatWhile(/[\w\-]/); | ||||
// Keyword | ||||
r4105 | if (wordLookup.hasOwnProperty(stream.current())) { | |||
r1 | return styleLookup[stream.current()]; | |||
} else if (stream.current().match(symbol)) { | ||||
return "variable"; | ||||
} else { | ||||
stream.next(); | ||||
return "variable-2"; | ||||
} | ||||
} | ||||
} | ||||
function tokenComment(stream, state) { | ||||
r4105 | var maybeEnd = false, maybeNested = false, nestedCount = 0, ch; | |||
r1 | while ((ch = stream.next())) { | |||
if (ch == "/" && maybeEnd) { | ||||
r4105 | if (nestedCount > 0) { | |||
nestedCount--; | ||||
} else { | ||||
state.tokenize = tokenBase; | ||||
break; | ||||
} | ||||
} else if (ch == "*" && maybeNested) { | ||||
nestedCount++; | ||||
r1 | } | |||
maybeEnd = (ch == "*"); | ||||
r4105 | maybeNested = (ch == "/"); | |||
r1 | } | |||
return "comment"; | ||||
} | ||||
function tokenString(quote, style) { | ||||
return function(stream, state) { | ||||
r4105 | var escaped = false, next, end = false; | |||
r1 | while ((next = stream.next()) != null) { | |||
r4105 | if (next == quote && !escaped) { | |||
r1 | end = true; | |||
break; | ||||
} | ||||
r4105 | escaped = !escaped && next == "\\"; | |||
r1 | } | |||
r4105 | if (end || !escaped) { | |||
r1 | state.tokenize = tokenBase; | |||
r4105 | } | |||
r1 | return style; | |||
}; | ||||
} | ||||
// Interface | ||||
return { | ||||
startState: function() { | ||||
return { | ||||
tokenize: tokenBase, | ||||
currentIndent: 0 | ||||
}; | ||||
}, | ||||
token: function(stream, state) { | ||||
if (stream.eatSpace()) | ||||
return null; | ||||
var style = state.tokenize(stream, state); | ||||
return style; | ||||
}, | ||||
blockCommentStart: "/*", | ||||
blockCommentEnd: "*/" | ||||
}; | ||||
}); | ||||
CodeMirror.defineMIME("text/x-dylan", "dylan"); | ||||
}); | ||||