123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://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)
- // Plain browser env
- else 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',
- })
- })
|