2018-01-21 10:33:32 -05:00
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2018-10-07 12:02:07 +02:00
// Distributed under an MIT license: https://codemirror.net/LICENSE
2018-01-21 10:33:32 -05:00
// 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" ) ;
} ) ;