GPQAPP
176 строк · 5.5 Кб
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4// Mathematica mode copyright (c) 2015 by Calin Barbat
5// Based on code by Patrick Scheibe (halirutan)
6// See: https://github.com/halirutan/Mathematica-Source-Highlighting/tree/master/src/lang-mma.js
7
8(function(mod) {9if (typeof exports == "object" && typeof module == "object") // CommonJS10mod(require("../../lib/codemirror"));11else if (typeof define == "function" && define.amd) // AMD12define(["../../lib/codemirror"], mod);13else // Plain browser env14mod(CodeMirror);15})(function(CodeMirror) {16"use strict";17
18CodeMirror.defineMode('mathematica', function(_config, _parserConfig) {19
20// used pattern building blocks21var Identifier = '[a-zA-Z\\$][a-zA-Z0-9\\$]*';22var pBase = "(?:\\d+)";23var pFloat = "(?:\\.\\d+|\\d+\\.\\d*|\\d+)";24var pFloatBase = "(?:\\.\\w+|\\w+\\.\\w*|\\w+)";25var pPrecision = "(?:`(?:`?"+pFloat+")?)";26
27// regular expressions28var reBaseForm = new RegExp('(?:'+pBase+'(?:\\^\\^'+pFloatBase+pPrecision+'?(?:\\*\\^[+-]?\\d+)?))');29var reFloatForm = new RegExp('(?:' + pFloat + pPrecision + '?(?:\\*\\^[+-]?\\d+)?)');30var reIdInContext = new RegExp('(?:`?)(?:' + Identifier + ')(?:`(?:' + Identifier + '))*(?:`?)');31
32function tokenBase(stream, state) {33var ch;34
35// get next character36ch = stream.next();37
38// string39if (ch === '"') {40state.tokenize = tokenString;41return state.tokenize(stream, state);42}43
44// comment45if (ch === '(') {46if (stream.eat('*')) {47state.commentLevel++;48state.tokenize = tokenComment;49return state.tokenize(stream, state);50}51}52
53// go back one character54stream.backUp(1);55
56// look for numbers57// Numbers in a baseform58if (stream.match(reBaseForm, true, false)) {59return 'number';60}61
62// Mathematica numbers. Floats (1.2, .2, 1.) can have optionally a precision (`float) or an accuracy definition63// (``float). Note: while 1.2` is possible 1.2`` is not. At the end an exponent (float*^+12) can follow.64if (stream.match(reFloatForm, true, false)) {65return 'number';66}67
68/* In[23] and Out[34] */69if (stream.match(/(?:In|Out)\[[0-9]*\]/, true, false)) {70return 'atom';71}72
73// usage74if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*(?:`[a-zA-Z0-9\$]+)*::usage)/, true, false)) {75return 'meta';76}77
78// message79if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*(?:`[a-zA-Z0-9\$]+)*::[a-zA-Z\$][a-zA-Z0-9\$]*):?/, true, false)) {80return 'string-2';81}82
83// this makes a look-ahead match for something like variable:{_Integer}84// the match is then forwarded to the mma-patterns tokenizer.85if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*\s*:)(?:(?:[a-zA-Z\$][a-zA-Z0-9\$]*)|(?:[^:=>~@\^\&\*\)\[\]'\?,\|])).*/, true, false)) {86return 'variable-2';87}88
89// catch variables which are used together with Blank (_), BlankSequence (__) or BlankNullSequence (___)90// Cannot start with a number, but can have numbers at any other position. Examples91// blub__Integer, a1_, b34_Integer3292if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {93return 'variable-2';94}95if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+/, true, false)) {96return 'variable-2';97}98if (stream.match(/_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {99return 'variable-2';100}101
102// Named characters in Mathematica, like \[Gamma].103if (stream.match(/\\\[[a-zA-Z\$][a-zA-Z0-9\$]*\]/, true, false)) {104return 'variable-3';105}106
107// Match all braces separately108if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) {109return 'bracket';110}111
112// Catch Slots (#, ##, #3, ##9 and the V10 named slots #name). I have never seen someone using more than one digit after #, so we match113// only one.114if (stream.match(/(?:#[a-zA-Z\$][a-zA-Z0-9\$]*|#+[0-9]?)/, true, false)) {115return 'variable-2';116}117
118// Literals like variables, keywords, functions119if (stream.match(reIdInContext, true, false)) {120return 'keyword';121}122
123// operators. Note that operators like @@ or /; are matched separately for each symbol.124if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) {125return 'operator';126}127
128// everything else is an error129stream.next(); // advance the stream.130return 'error';131}132
133function tokenString(stream, state) {134var next, end = false, escaped = false;135while ((next = stream.next()) != null) {136if (next === '"' && !escaped) {137end = true;138break;139}140escaped = !escaped && next === '\\';141}142if (end && !escaped) {143state.tokenize = tokenBase;144}145return 'string';146};147
148function tokenComment(stream, state) {149var prev, next;150while(state.commentLevel > 0 && (next = stream.next()) != null) {151if (prev === '(' && next === '*') state.commentLevel++;152if (prev === '*' && next === ')') state.commentLevel--;153prev = next;154}155if (state.commentLevel <= 0) {156state.tokenize = tokenBase;157}158return 'comment';159}160
161return {162startState: function() {return {tokenize: tokenBase, commentLevel: 0};},163token: function(stream, state) {164if (stream.eatSpace()) return null;165return state.tokenize(stream, state);166},167blockCommentStart: "(*",168blockCommentEnd: "*)"169};170});171
172CodeMirror.defineMIME('text/x-mathematica', {173name: 'mathematica'174});175
176});177