// 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' CodeMirror.defineMode('ebnf', function (config) { var commentType = { slash: 0, parenthesis: 1 } var stateType = { comment: 0, _string: 1, characterClass: 2 } var bracesMode = null if (config.bracesMode) bracesMode = CodeMirror.getMode(config, config.bracesMode) return { startState: function () { return { stringType: null, commentType: null, braced: 0, lhs: true, localState: null, stack: [], inDefinition: false, } }, token: function (stream, state) { if (!stream) return //check for state changes if (state.stack.length === 0) { //strings if (stream.peek() == '"' || stream.peek() == "'") { state.stringType = stream.peek() stream.next() // Skip quote state.stack.unshift(stateType._string) } else if (stream.match('/*')) { //comments starting with /* state.stack.unshift(stateType.comment) state.commentType = commentType.slash } else if (stream.match('(*')) { //comments starting with (* state.stack.unshift(stateType.comment) state.commentType = commentType.parenthesis } } //return state //stack has switch (state.stack[0]) { case stateType._string: while (state.stack[0] === stateType._string && !stream.eol()) { if (stream.peek() === state.stringType) { stream.next() // Skip quote state.stack.shift() // Clear flag } else if (stream.peek() === '\\') { stream.next() stream.next() } else { stream.match(/^.[^\\\"\']*/) } } return state.lhs ? 'property string' : 'string' // Token style case stateType.comment: while (state.stack[0] === stateType.comment && !stream.eol()) { if (state.commentType === commentType.slash && stream.match('*/')) { state.stack.shift() // Clear flag state.commentType = null } else if (state.commentType === commentType.parenthesis && stream.match('*)')) { state.stack.shift() // Clear flag state.commentType = null } else { stream.match(/^.[^\*]*/) } } return 'comment' case stateType.characterClass: while (state.stack[0] === stateType.characterClass && !stream.eol()) { if (!(stream.match(/^[^\]\\]+/) || stream.match('.'))) { state.stack.shift() } } return 'operator' } var peek = stream.peek() if (bracesMode !== null && (state.braced || peek === '{')) { if (state.localState === null) state.localState = CodeMirror.startState(bracesMode) var token = bracesMode.token(stream, state.localState), text = stream.current() if (!token) { for (var i = 0; i < text.length; i++) { if (text[i] === '{') { if (state.braced === 0) { token = 'matchingbracket' } state.braced++ } else if (text[i] === '}') { state.braced-- if (state.braced === 0) { token = 'matchingbracket' } } } } return token } //no stack switch (peek) { case '[': stream.next() state.stack.unshift(stateType.characterClass) return 'bracket' case ':': case '|': case ';': stream.next() return 'operator' case '%': if (stream.match('%%')) { return 'header' } else if (stream.match(/[%][A-Za-z]+/)) { return 'keyword' } else if (stream.match(/[%][}]/)) { return 'matchingbracket' } break case '/': if (stream.match(/[\/][A-Za-z]+/)) { return 'keyword' } case '\\': if (stream.match(/[\][a-z]+/)) { return 'string-2' } case '.': if (stream.match('.')) { return 'atom' } case '*': case '-': case '+': case '^': if (stream.match(peek)) { return 'atom' } case '$': if (stream.match('$$')) { return 'builtin' } else if (stream.match(/[$][0-9]+/)) { return 'variable-3' } case '<': if (stream.match(/<<[a-zA-Z_]+>>/)) { return 'builtin' } } if (stream.match('//')) { stream.skipToEnd() return 'comment' } else if (stream.match('return')) { return 'operator' } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) { if (stream.match(/(?=[\(.])/)) { return 'variable' } else if (stream.match(/(?=[\s\n]*[:=])/)) { return 'def' } return 'variable-2' } else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) { stream.next() return 'bracket' } else if (!stream.eatSpace()) { stream.next() } return null }, } }) CodeMirror.defineMIME('text/x-ebnf', 'ebnf') })