forth.js
180 lines
| 5.1 KiB
| application/javascript
|
JavascriptLexer
r1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others | |||
r4105 | // Distributed under an MIT license: https://codemirror.net/LICENSE | |||
r1 | ||||
// 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"); | ||||
}); | ||||