mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
5.3 KiB
204 lines
5.3 KiB
// CodeMirror, copyright (c) by Marijn Haverbeke and others |
|
// Distributed under an MIT license: http://codemirror.net/LICENSE |
|
|
|
// Yacas mode copyright (c) 2015 by Grzegorz Mazur |
|
// Loosely based on mathematica mode by Calin Barbat |
|
|
|
(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('yacas', function(_config, _parserConfig) { |
|
|
|
function words(str) { |
|
var obj = {}, words = str.split(" "); |
|
for (var i = 0; i < words.length; ++i) obj[words[i]] = true; |
|
return obj; |
|
} |
|
|
|
var bodiedOps = words("Assert BackQuote D Defun Deriv For ForEach FromFile " + |
|
"FromString Function Integrate InverseTaylor Limit " + |
|
"LocalSymbols Macro MacroRule MacroRulePattern " + |
|
"NIntegrate Rule RulePattern Subst TD TExplicitSum " + |
|
"TSum Taylor Taylor1 Taylor2 Taylor3 ToFile " + |
|
"ToStdout ToString TraceRule Until While"); |
|
|
|
// patterns |
|
var pFloatForm = "(?:(?:\\.\\d+|\\d+\\.\\d*|\\d+)(?:[eE][+-]?\\d+)?)"; |
|
var pIdentifier = "(?:[a-zA-Z\\$'][a-zA-Z0-9\\$']*)"; |
|
|
|
// regular expressions |
|
var reFloatForm = new RegExp(pFloatForm); |
|
var reIdentifier = new RegExp(pIdentifier); |
|
var rePattern = new RegExp(pIdentifier + "?_" + pIdentifier); |
|
var reFunctionLike = new RegExp(pIdentifier + "\\s*\\("); |
|
|
|
function tokenBase(stream, state) { |
|
var ch; |
|
|
|
// get next character |
|
ch = stream.next(); |
|
|
|
// string |
|
if (ch === '"') { |
|
state.tokenize = tokenString; |
|
return state.tokenize(stream, state); |
|
} |
|
|
|
// comment |
|
if (ch === '/') { |
|
if (stream.eat('*')) { |
|
state.tokenize = tokenComment; |
|
return state.tokenize(stream, state); |
|
} |
|
if (stream.eat("/")) { |
|
stream.skipToEnd(); |
|
return "comment"; |
|
} |
|
} |
|
|
|
// go back one character |
|
stream.backUp(1); |
|
|
|
// update scope info |
|
var m = stream.match(/^(\w+)\s*\(/, false); |
|
if (m !== null && bodiedOps.hasOwnProperty(m[1])) |
|
state.scopes.push('bodied'); |
|
|
|
var scope = currentScope(state); |
|
|
|
if (scope === 'bodied' && ch === '[') |
|
state.scopes.pop(); |
|
|
|
if (ch === '[' || ch === '{' || ch === '(') |
|
state.scopes.push(ch); |
|
|
|
scope = currentScope(state); |
|
|
|
if (scope === '[' && ch === ']' || |
|
scope === '{' && ch === '}' || |
|
scope === '(' && ch === ')') |
|
state.scopes.pop(); |
|
|
|
if (ch === ';') { |
|
while (scope === 'bodied') { |
|
state.scopes.pop(); |
|
scope = currentScope(state); |
|
} |
|
} |
|
|
|
// look for ordered rules |
|
if (stream.match(/\d+ *#/, true, false)) { |
|
return 'qualifier'; |
|
} |
|
|
|
// look for numbers |
|
if (stream.match(reFloatForm, true, false)) { |
|
return 'number'; |
|
} |
|
|
|
// look for placeholders |
|
if (stream.match(rePattern, true, false)) { |
|
return 'variable-3'; |
|
} |
|
|
|
// match all braces separately |
|
if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) { |
|
return 'bracket'; |
|
} |
|
|
|
// literals looking like function calls |
|
if (stream.match(reFunctionLike, true, false)) { |
|
stream.backUp(1); |
|
return 'variable'; |
|
} |
|
|
|
// all other identifiers |
|
if (stream.match(reIdentifier, true, false)) { |
|
return 'variable-2'; |
|
} |
|
|
|
// operators; note that operators like @@ or /; are matched separately for each symbol. |
|
if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) { |
|
return 'operator'; |
|
} |
|
|
|
// everything else is an error |
|
return 'error'; |
|
} |
|
|
|
function tokenString(stream, state) { |
|
var next, end = false, escaped = false; |
|
while ((next = stream.next()) != null) { |
|
if (next === '"' && !escaped) { |
|
end = true; |
|
break; |
|
} |
|
escaped = !escaped && next === '\\'; |
|
} |
|
if (end && !escaped) { |
|
state.tokenize = tokenBase; |
|
} |
|
return 'string'; |
|
}; |
|
|
|
function tokenComment(stream, state) { |
|
var prev, next; |
|
while((next = stream.next()) != null) { |
|
if (prev === '*' && next === '/') { |
|
state.tokenize = tokenBase; |
|
break; |
|
} |
|
prev = next; |
|
} |
|
return 'comment'; |
|
} |
|
|
|
function currentScope(state) { |
|
var scope = null; |
|
if (state.scopes.length > 0) |
|
scope = state.scopes[state.scopes.length - 1]; |
|
return scope; |
|
} |
|
|
|
return { |
|
startState: function() { |
|
return { |
|
tokenize: tokenBase, |
|
scopes: [] |
|
}; |
|
}, |
|
token: function(stream, state) { |
|
if (stream.eatSpace()) return null; |
|
return state.tokenize(stream, state); |
|
}, |
|
indent: function(state, textAfter) { |
|
if (state.tokenize !== tokenBase && state.tokenize !== null) |
|
return CodeMirror.Pass; |
|
|
|
var delta = 0; |
|
if (textAfter === ']' || textAfter === '];' || |
|
textAfter === '}' || textAfter === '};' || |
|
textAfter === ');') |
|
delta = -1; |
|
|
|
return (state.scopes.length + delta) * _config.indentUnit; |
|
}, |
|
electricChars: "{}[]();", |
|
blockCommentStart: "/*", |
|
blockCommentEnd: "*/", |
|
lineComment: "//" |
|
}; |
|
}); |
|
|
|
CodeMirror.defineMIME('text/x-yacas', { |
|
name: 'yacas' |
|
}); |
|
|
|
});
|
|
|