Spaces:
Running
Running
// CodeMirror, copyright (c) by Marijn Haverbeke and others | |
// Distributed under an MIT license: http://codemirror.net/LICENSE | |
// Author: Aliaksei Chapyzhenka | |
(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"; | |
function toWordList(words) { | |
var ret = []; | |
words.split(' ').forEach(function(e){ | |
ret.push({name: e}); | |
}); | |
return ret; | |
} | |
var coreWordList = toWordList( | |
'INVERT AND OR XOR\ | |
2* 2/ LSHIFT RSHIFT\ | |
0= = 0< < > U< MIN MAX\ | |
2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP\ | |
>R R> R@\ | |
+ - 1+ 1- ABS NEGATE\ | |
S>D * M* UM*\ | |
FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD\ | |
HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2!\ | |
ALIGN ALIGNED +! ALLOT\ | |
CHAR [CHAR] [ ] BL\ | |
FIND EXECUTE IMMEDIATE COUNT LITERAL STATE\ | |
; DOES> >BODY\ | |
EVALUATE\ | |
SOURCE >IN\ | |
<# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL\ | |
FILL MOVE\ | |
. CR EMIT SPACE SPACES TYPE U. .R U.R\ | |
ACCEPT\ | |
TRUE FALSE\ | |
<> U> 0<> 0>\ | |
NIP TUCK ROLL PICK\ | |
2>R 2R@ 2R>\ | |
WITHIN UNUSED MARKER\ | |
I J\ | |
TO\ | |
COMPILE, [COMPILE]\ | |
SAVE-INPUT RESTORE-INPUT\ | |
PAD ERASE\ | |
2LITERAL DNEGATE\ | |
D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS\ | |
M+ M*/ D. D.R 2ROT DU<\ | |
CATCH THROW\ | |
FREE RESIZE ALLOCATE\ | |
CS-PICK CS-ROLL\ | |
GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER\ | |
PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER\ | |
-TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL'); | |
var immediateWordList = toWordList('IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE [IF] [ELSE] [THEN] ?DO DO LOOP +LOOP UNLOOP LEAVE EXIT AGAIN CASE OF ENDOF ENDCASE'); | |
CodeMirror.defineMode('forth', function() { | |
function searchWordList (wordList, word) { | |
var i; | |
for (i = wordList.length - 1; i >= 0; i--) { | |
if (wordList[i].name === word.toUpperCase()) { | |
return wordList[i]; | |
} | |
} | |
return undefined; | |
} | |
return { | |
startState: function() { | |
return { | |
state: '', | |
base: 10, | |
coreWordList: coreWordList, | |
immediateWordList: immediateWordList, | |
wordList: [] | |
}; | |
}, | |
token: function (stream, stt) { | |
var mat; | |
if (stream.eatSpace()) { | |
return null; | |
} | |
if (stt.state === '') { // interpretation | |
if (stream.match(/^(\]|:NONAME)(\s|$)/i)) { | |
stt.state = ' compilation'; | |
return 'builtin compilation'; | |
} | |
mat = stream.match(/^(\:)\s+(\S+)(\s|$)+/); | |
if (mat) { | |
stt.wordList.push({name: mat[2].toUpperCase()}); | |
stt.state = ' compilation'; | |
return 'def' + stt.state; | |
} | |
mat = stream.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i); | |
if (mat) { | |
stt.wordList.push({name: mat[2].toUpperCase()}); | |
return 'def' + stt.state; | |
} | |
mat = stream.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/); | |
if (mat) { | |
return 'builtin' + stt.state; | |
} | |
} else { // compilation | |
// ; [ | |
if (stream.match(/^(\;|\[)(\s)/)) { | |
stt.state = ''; | |
stream.backUp(1); | |
return 'builtin compilation'; | |
} | |
if (stream.match(/^(\;|\[)($)/)) { | |
stt.state = ''; | |
return 'builtin compilation'; | |
} | |
if (stream.match(/^(POSTPONE)\s+\S+(\s|$)+/)) { | |
return 'builtin'; | |
} | |
} | |
// dynamic wordlist | |
mat = stream.match(/^(\S+)(\s+|$)/); | |
if (mat) { | |
if (searchWordList(stt.wordList, mat[1]) !== undefined) { | |
return 'variable' + stt.state; | |
} | |
// comments | |
if (mat[1] === '\\') { | |
stream.skipToEnd(); | |
return 'comment' + stt.state; | |
} | |
// core words | |
if (searchWordList(stt.coreWordList, mat[1]) !== undefined) { | |
return 'builtin' + stt.state; | |
} | |
if (searchWordList(stt.immediateWordList, mat[1]) !== undefined) { | |
return 'keyword' + stt.state; | |
} | |
if (mat[1] === '(') { | |
stream.eatWhile(function (s) { return s !== ')'; }); | |
stream.eat(')'); | |
return 'comment' + stt.state; | |
} | |
// // strings | |
if (mat[1] === '.(') { | |
stream.eatWhile(function (s) { return s !== ')'; }); | |
stream.eat(')'); | |
return 'string' + stt.state; | |
} | |
if (mat[1] === 'S"' || mat[1] === '."' || mat[1] === 'C"') { | |
stream.eatWhile(function (s) { return s !== '"'; }); | |
stream.eat('"'); | |
return 'string' + stt.state; | |
} | |
// numbers | |
if (mat[1] - 0xfffffffff) { | |
return 'number' + stt.state; | |
} | |
// if (mat[1].match(/^[-+]?[0-9]+\.[0-9]*/)) { | |
// return 'number' + stt.state; | |
// } | |
return 'atom' + stt.state; | |
} | |
} | |
}; | |
}); | |
CodeMirror.defineMIME("text/x-forth", "forth"); | |
}); | |