forth.js (5230B)
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://codemirror.net/LICENSE 3 4 // Author: Aliaksei Chapyzhenka 5 6 (function(mod) { 7 if (typeof exports == "object" && typeof module == "object") // CommonJS 8 mod(require("../../lib/codemirror")); 9 else if (typeof define == "function" && define.amd) // AMD 10 define(["../../lib/codemirror"], mod); 11 else // Plain browser env 12 mod(CodeMirror); 13 })(function(CodeMirror) { 14 "use strict"; 15 16 function toWordList(words) { 17 var ret = []; 18 words.split(' ').forEach(function(e){ 19 ret.push({name: e}); 20 }); 21 return ret; 22 } 23 24 var coreWordList = toWordList( 25 'INVERT AND OR XOR\ 26 2* 2/ LSHIFT RSHIFT\ 27 0= = 0< < > U< MIN MAX\ 28 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP\ 29 >R R> R@\ 30 + - 1+ 1- ABS NEGATE\ 31 S>D * M* UM*\ 32 FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD\ 33 HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2!\ 34 ALIGN ALIGNED +! ALLOT\ 35 CHAR [CHAR] [ ] BL\ 36 FIND EXECUTE IMMEDIATE COUNT LITERAL STATE\ 37 ; DOES> >BODY\ 38 EVALUATE\ 39 SOURCE >IN\ 40 <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL\ 41 FILL MOVE\ 42 . CR EMIT SPACE SPACES TYPE U. .R U.R\ 43 ACCEPT\ 44 TRUE FALSE\ 45 <> U> 0<> 0>\ 46 NIP TUCK ROLL PICK\ 47 2>R 2R@ 2R>\ 48 WITHIN UNUSED MARKER\ 49 I J\ 50 TO\ 51 COMPILE, [COMPILE]\ 52 SAVE-INPUT RESTORE-INPUT\ 53 PAD ERASE\ 54 2LITERAL DNEGATE\ 55 D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS\ 56 M+ M*/ D. D.R 2ROT DU<\ 57 CATCH THROW\ 58 FREE RESIZE ALLOCATE\ 59 CS-PICK CS-ROLL\ 60 GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER\ 61 PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER\ 62 -TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL'); 63 64 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'); 65 66 CodeMirror.defineMode('forth', function() { 67 function searchWordList (wordList, word) { 68 var i; 69 for (i = wordList.length - 1; i >= 0; i--) { 70 if (wordList[i].name === word.toUpperCase()) { 71 return wordList[i]; 72 } 73 } 74 return undefined; 75 } 76 return { 77 startState: function() { 78 return { 79 state: '', 80 base: 10, 81 coreWordList: coreWordList, 82 immediateWordList: immediateWordList, 83 wordList: [] 84 }; 85 }, 86 token: function (stream, stt) { 87 var mat; 88 if (stream.eatSpace()) { 89 return null; 90 } 91 if (stt.state === '') { // interpretation 92 if (stream.match(/^(\]|:NONAME)(\s|$)/i)) { 93 stt.state = ' compilation'; 94 return 'builtin compilation'; 95 } 96 mat = stream.match(/^(\:)\s+(\S+)(\s|$)+/); 97 if (mat) { 98 stt.wordList.push({name: mat[2].toUpperCase()}); 99 stt.state = ' compilation'; 100 return 'def' + stt.state; 101 } 102 mat = stream.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i); 103 if (mat) { 104 stt.wordList.push({name: mat[2].toUpperCase()}); 105 return 'def' + stt.state; 106 } 107 mat = stream.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/); 108 if (mat) { 109 return 'builtin' + stt.state; 110 } 111 } else { // compilation 112 // ; [ 113 if (stream.match(/^(\;|\[)(\s)/)) { 114 stt.state = ''; 115 stream.backUp(1); 116 return 'builtin compilation'; 117 } 118 if (stream.match(/^(\;|\[)($)/)) { 119 stt.state = ''; 120 return 'builtin compilation'; 121 } 122 if (stream.match(/^(POSTPONE)\s+\S+(\s|$)+/)) { 123 return 'builtin'; 124 } 125 } 126 127 // dynamic wordlist 128 mat = stream.match(/^(\S+)(\s+|$)/); 129 if (mat) { 130 if (searchWordList(stt.wordList, mat[1]) !== undefined) { 131 return 'variable' + stt.state; 132 } 133 134 // comments 135 if (mat[1] === '\\') { 136 stream.skipToEnd(); 137 return 'comment' + stt.state; 138 } 139 140 // core words 141 if (searchWordList(stt.coreWordList, mat[1]) !== undefined) { 142 return 'builtin' + stt.state; 143 } 144 if (searchWordList(stt.immediateWordList, mat[1]) !== undefined) { 145 return 'keyword' + stt.state; 146 } 147 148 if (mat[1] === '(') { 149 stream.eatWhile(function (s) { return s !== ')'; }); 150 stream.eat(')'); 151 return 'comment' + stt.state; 152 } 153 154 // // strings 155 if (mat[1] === '.(') { 156 stream.eatWhile(function (s) { return s !== ')'; }); 157 stream.eat(')'); 158 return 'string' + stt.state; 159 } 160 if (mat[1] === 'S"' || mat[1] === '."' || mat[1] === 'C"') { 161 stream.eatWhile(function (s) { return s !== '"'; }); 162 stream.eat('"'); 163 return 'string' + stt.state; 164 } 165 166 // numbers 167 if (mat[1] - 0xfffffffff) { 168 return 'number' + stt.state; 169 } 170 // if (mat[1].match(/^[-+]?[0-9]+\.[0-9]*/)) { 171 // return 'number' + stt.state; 172 // } 173 174 return 'atom' + stt.state; 175 } 176 } 177 }; 178 }); 179 CodeMirror.defineMIME("text/x-forth", "forth"); 180 });