2018-01-21 23:33:32 +08:00
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2018-10-07 18:02:07 +08:00
// Distributed under an MIT license: https://codemirror.net/LICENSE
2018-01-21 23:33:32 +08: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 \
2 DROP 2 DUP 2 OVER 2 SWAP ? DUP DEPTH DROP DUP OVER ROT SWAP \
> R R > R @ \
+ - 1 + 1 - ABS NEGATE \
S > D * M * UM * \
FM / MOD SM / REM UM / MOD * / * / M O D / / M O D M O D \
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 2 R @ 2 R > \
WITHIN UNUSED MARKER \
I J \
TO \
COMPILE , [ COMPILE ] \
SAVE - INPUT RESTORE - INPUT \
PAD ERASE \
2 LITERAL DNEGATE \
D - D + D0 < D0 = D2 * D2 / D < D = DMAX DMIN D > S DABS \
M + M * / D . D . R 2 R O T D U < \
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" ) ;
} ) ;