// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://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) // Plain browser env else mod(CodeMirror) })(function (CodeMirror) { 'use strict' 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 } 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 = {} forEach(['keyword', 'definition', 'simpleDefinition', 'signalingCalls'], function (type) { forEach(words[type], function (word) { 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' } stream.backUp(1) } // Decimal 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' } } // Hash else if (ch == '#') { stream.next() // Symbol with string syntax ch = stream.peek() if (ch == '"') { stream.next() return chain(stream, state, tokenString('"', 'string')) } // 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' } // Token concatenation in macros else if (ch == '#') { stream.next() return 'punctuation' } // Sequence literals else if (ch == '[' || ch == '(') { stream.next() return 'bracket' // Hash symbol } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) { return 'atom' } else { stream.eatWhile(/[-a-zA-Z]/) 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' } 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' } else if (stream.match('end')) { return 'keyword' } for (var name in patterns) { if (patterns.hasOwnProperty(name)) { var pattern = patterns[name] if ( (pattern instanceof Array && some(pattern, function (p) { return stream.match(p) })) || stream.match(pattern) ) return patternStyles[name] } } if (/[+\-*\/^=<>&|]/.test(ch)) { stream.next() return 'operator' } if (stream.match('define')) { return 'def' } else { stream.eatWhile(/[\w\-]/) // Keyword if (wordLookup.hasOwnProperty(stream.current())) { return styleLookup[stream.current()] } else if (stream.current().match(symbol)) { return 'variable' } else { stream.next() return 'variable-2' } } } function tokenComment(stream, state) { var maybeEnd = false, maybeNested = false, nestedCount = 0, ch while ((ch = stream.next())) { if (ch == '/' && maybeEnd) { if (nestedCount > 0) { nestedCount-- } else { state.tokenize = tokenBase break } } else if (ch == '*' && maybeNested) { nestedCount++ } maybeEnd = ch == '*' maybeNested = ch == '/' } return 'comment' } function tokenString(quote, style) { return function (stream, state) { var escaped = false, next, end = false while ((next = stream.next()) != null) { if (next == quote && !escaped) { end = true break } escaped = !escaped && next == '\\' } if (end || !escaped) { state.tokenize = tokenBase } 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') })