Advertisement
12Me21

ex

Apr 10th, 2018
402
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.04 KB | None | 0 0
  1. //list of keywords
  2. //does not include OPERATORS or CONSTANTS or fake keywords TO/STEP
  3. var KEYWORDS=["BREAK","CALL","COMMON","CONTINUE","DATA","DEC","DEF","DIM","ELSE","ELSEIF","END","ENDIF","EXEC","FOR","GOSUB","GOTO","IF","INC","INPUT","LINPUT","NEXT","ON","OUT","PRINT","READ","REM","REPEAT","RESTORE","RETURN","STOP","SWAP","THEN","UNTIL","USE","VAR","WEND","WHILE"];
  4. //built-in functions
  5. var BUILTINS=["ABS","ACCEL","ACLS","ACOS","ARYOP","ASC","ASIN","ATAN","ATTR","BACKCOLOR","BACKTRACE","BEEP","BGANIM","BGCHK","BGCLIP","BGCLR","BGCOLOR","BGCOORD","BGCOPY","BGFILL","BGFUNC","BGGET","BGHIDE","BGHOME","BGLOAD","BGMCHK","BGMCLEAR","BGMCONT","BGMPAUSE","BGMPLAY","BGMPRG","BGMPRGA","BGMSET","BGMSETD","BGMSTOP","BGMVAR","BGMVOL","BGOFS","BGPAGE","BGPUT","BGROT","BGSAVE","BGSCALE","BGSCREEN","BGSHOW","BGSTART","BGSTOP","BGVAR","BIN$","BIQUAD","BQPARAM","BREPEAT","BUTTON","CEIL","CHKCALL","CHKCHR","CHKFILE","CHKLABEL","CHKVAR","CHR$","CLASSIFY","CLIPBOARD","CLS","COLOR","CONTROLLER","COPY","COS","COSH","DEG","DELETE","DIALOG","DISPLAY","DLCOPEN","DTREAD","EFCOFF","EFCON","EFCSET","EFCWET","EXP","EXTFEATURE","FADE","FADECHK","FFT","FFTWFN","FILES","FILL","FLOOR","FONTDEF","FORMAT$","GBOX","GCIRCLE","GCLIP","GCLS","GCOLOR","GCOPY","GFILL","GLINE","GLOAD","GOFS","GPAGE","GPAINT","GPRIO","GPSET","GPUTCHR","GSAVE","GSPOIT","GTRI","GYROA","GYROSYNC","GYROV","HEX$","IFFT","INKEY$","INSTR","KEY","LEFT$","LEN","LOAD","LOCATE","LOG","MAX","MICDATA","MICSAVE","MICSTART","MICSTOP","MID$","MIN","MPEND","MPGET","MPNAME$","MPRECV","MPSEND","MPSET","MPSTART","MPSTAT","PCMCONT","PCMSTOP","PCMSTREAM","PCMVOL","POP","POW","PRGDEL","PRGEDIT","PRGGET$","PRGINS","PRGNAME$","PRGSET","PRGSIZE","PROJECT","PUSH","RAD","RANDOMIZE","RENAME","RGB","RGBREAD","RIGHT$","RINGCOPY","RND","RNDF","ROUND","RSORT","SAVE","SCROLL","SGN","SHIFT","SIN","SINH","SNDSTOP","SORT","SPANIM","SPCHK","SPCHR","SPCLIP","SPCLR","SPCOL","SPCOLOR","SPCOLVEC","SPDEF","SPFUNC","SPHIDE","SPHITINFO","SPHITRC","SPHITSP","SPHOME","SPLINK","SPOFS","SPPAGE","SPROT","SPSCALE","SPSET","SPSHOW","SPSTART","SPSTOP","SPUNLINK","SPUSED","SPVAR","SQR","STICK","STICKEX","STR$","SUBST$","TALK","TALKCHK","TALKSTOP","TAN","TANH","TMREAD","TOUCH","UNSHIFT","VAL","VISIBLE","VSYNC","WAIT","WAVSET","WAVSETA","WIDTH","XSCREEN"];
  6. //system variables
  7. var SYSTEMVARS=["CALLIDX","CSRX","CSRY","CSRZ","DATE$","ERRLINE","ERRNUM","ERRPRG","FREEMEM","HARDWARE","MAINCNT","MICPOS", "MICSIZE","MILLISEC","MPCOUNT","MPHOST","MPLOCAL","PCMPOS","PRGSLOT","RESULT","SYSBEEP","TABSTEP","TIME$","VERSION"];
  8.  
  9. //parser
  10. //nextToken: function that returns the next token
  11. //callback: output function
  12. function parse(nextToken){
  13. //current token
  14. var type,text,word; //NOTE: word is only update right after next()ing. don't rely on it laaaaater
  15. //stored tokens
  16. var newType,newText,newWord;
  17. //keep track of stored tokens
  18. var readNext=1;
  19. //false=not, 1=no paren, 2=()
  20. var defType=false,nextDefCommon=false;
  21.  
  22. var blocks=[];
  23. var current={};
  24. var currentBlocks=[];
  25.  
  26. function startBlock(){
  27. current.code=[];
  28. currentBlocks.push(current);
  29. current={};
  30. }
  31. function endBlock(){
  32. var block=currentBlocks.pop();
  33. currentBlocks[currentBlocks.length-1].code.push(block);
  34. }
  35.  
  36. current.type="main";
  37. startBlock();
  38.  
  39. do{
  40. try{
  41. readStatement();
  42. }catch(error){
  43. if(error.name==="ParseError"){
  44. return error.message;
  45. //bad error!!!
  46. }else{
  47. throw error;
  48. return;
  49. }
  50. }
  51. }while(type!=="eof");;;
  52.  
  53. //read a "line" of code
  54. function readStatement(){
  55. next();
  56. switch(type){
  57. //keywords with no arguments
  58. case "BREAK":
  59. current.type="BREAK";
  60. break;case "CONTINUE":
  61. current.type="CONTINUE";
  62. break;case "ELSE":
  63. assert(currentBlock().type=="IF"||currentBlock().type=="ELSEIF","ELSE without IF");
  64. endBlock();
  65. current.type="ELSE";
  66. startBlock();
  67. break;case "ENDIF":
  68. assert(currentBlock().type=="IF","WEND without WHILE");
  69. endBlock();
  70. break;case "STOP":
  71. current.type="STOP";
  72. break;case "REPEAT":
  73. current.type="REPEAT";
  74. startBlock();
  75. break;case "WEND":
  76. assert(currentBlock().type=="WHILE","WEND without WHILE");
  77. endBlock();
  78. //CALL
  79. break;case "CALL":
  80. current.type="CALL";
  81. //CALL SPRITE and CALL BG
  82. if(peekWord("SPRITE")||peekWord("BG")){
  83. readToken("word");
  84. current.mode=""//TODO: sprite or BG
  85. //regular CALL
  86. }else{
  87. current.inputs=readList(readExpression);
  88. if(readToken("OUT","keyword"))
  89. current.outputs=readList(readVariable);
  90. }
  91. //COMMON
  92. break;case "COMMON":
  93. assert(peekToken("DEF"),"COMMON without DEF");
  94. nextDefCommon=true;
  95. //DATA
  96. break;case "DATA":
  97. current.type="DATA";
  98. assert(current.inputs=readList(readExpression,true),"Missing list"); //should read constant expression
  99. //SWAP
  100. break;case "SWAP":
  101. current.type="SWAP";
  102. assert(current.variable=readVariable(),"Missing variable in SWAP");
  103. assert(readToken(","),"Missing comma in SWAP");
  104. assert(current.variable2=readVariable(),"Missing variable in SWAP");
  105. //READ
  106. break;case "READ":
  107. current.type="READ";
  108. assert(current.inputs=readList(readVariable,true),"Missing list");
  109. //DEC/INC
  110. break;case "DEC":
  111. current.type="DEC";
  112. assert(current.variable=readVariable(),"Missing DEC variable");
  113. if(readToken(","))
  114. assert(current.value=readExpression(),"Missing DEC amount");
  115. break;case "INC":
  116. current.type="INC";
  117. assert(current.variable=readVariable(),"Missing INC variable");
  118. if(readToken(","))
  119. assert(current.value=readExpression(),"Missing INC amount");
  120. //DEF
  121. break;case "DEF":
  122. assert(!defType,"Nested DEF");
  123. current.type="DEF";
  124. if(nextDefCommon)
  125. current.common=true;
  126. nextDefCommon=false;
  127. //read function name
  128. assert(current.defName=readToken("word"),"Missing DEF name");
  129. //() form
  130. if(readToken("(")){
  131. defType=2;
  132. current.parenDef=true;
  133. //read argument list
  134. current.inputs=readList(readArgument,true);
  135. //read )
  136. assert(readToken(")"),"Missing \")\" after DEF arguments"
  137. );
  138. //subroutine/out form
  139. }else{
  140. defType=1;
  141. //read argument list
  142. current.inputs=readList(readArgument,true);
  143. //OUT
  144. //read output list
  145. if(readToken("OUT"))
  146. current.outputs=readList(readArgument,true);
  147. }
  148. startBlock();
  149. //VAR
  150. break;case "VAR":
  151. //assignment form
  152. if(peekToken("(")){
  153. current.type="assignment"
  154. readToken("(");
  155. assert(current.varName=readExpression(),"Missing var name");
  156. assert(readToken(")"),"missing )");
  157. //TODO - this
  158. while(readToken("[")){
  159. assert(readList(readExpression,true),"Missing array index");
  160. assert(readToken("]"),"Missing \"]\"");
  161. }
  162. assert(readToken("="),"missing =");
  163. current.value=readExpression();
  164. //normal form
  165. }else{
  166. current.type="DIM";
  167. assert(current.inputs=readDeclarationList(),"Missing variable list");
  168. }
  169. //DIM
  170. break;case "DIM":
  171. current.type="DIM";
  172. assert(current.inputs=readDeclarationList(),"Missing variable list");
  173. //IF, ELSEIF
  174. break;case "ELSEIF":
  175. assert(currentBlock().type=="IF"||currentBlock().type=="ELSEIF","ELSEIF without IF");
  176. endBlock();
  177. current.type="ELSEIF"
  178. current.condition=readExpression();
  179. startBlock();
  180. break;case "IF":
  181. current.type="IF"
  182. assert(current.condition=readExpression(),"Missing IF condition");
  183. assert(readToken("THEN")||readToken("GOTO"),"IF without THEN");
  184. //check goto vs then
  185. readToken("label");//optional
  186. startBlock();
  187. //END
  188. break;case "END":
  189. current.type="END";
  190. if(defType)
  191. defType=0;
  192. //EXEC/USE
  193. break;case "EXEC":
  194. current.type="EXEC";
  195. current.value=readExpression();
  196. break;case "USE":
  197. current.type="USE";
  198. current.value=readExpression();
  199. //FOR
  200. break;case "FOR":
  201. current.type="FOR";
  202. assert(current.variable=readVariable(),"Missing FOR variable");
  203. assert(readToken("="),"Missing = in FOR");
  204. current.start=readExpression();
  205. assert(readToken("word") && word==="TO","Missing TO in FOR");
  206. current.end=readExpression();
  207. if(readToken("word") && word==="STEP"){
  208. current.step=readExpression();
  209. }else
  210. readNext=0; //heck
  211. startBlock();
  212. //GOSUB GOTO RESTORE(?)
  213. break;case "GOSUB":
  214. current.type="GOSUB";
  215. if(!(current.label=readToken("label")))
  216. assert(current.label=readExpression(),"Missing argument to GOSUB");
  217. break;case "GOTO":
  218. current.type="GOTO";
  219. if(!(current.label=readToken("label")))
  220. assert(current.label=readExpression(),"Missing argument to GOTO");
  221. break;case "RESTORE":
  222. current.type="RESTORE";
  223. if(!(current.label=readToken("label")))
  224. assert(current.label=readExpression(),"Missing argument to RESTORE");
  225. //WHILE <condition>
  226. break;case "WHILE":
  227. current.type="WHILE"
  228. assert(current.condition=readExpression(),"Missing argument to keyword");
  229. startBlock();
  230. //UNTIL <condition>
  231. break;case "UNTIL":
  232. assert(currentBlock().type=="REPEAT","UNTIL without REPEAT");
  233. assert(currentBlock().condition=readExpression(),"Missing UNTIL condition");
  234. endBlock();
  235. //INPUT
  236. break;case "INPUT":
  237. current.type="INPUT";
  238. current.inputs=readPrintList(readExpression);
  239. //LINPUT
  240. break;case "LINPUT":
  241. current.type="LINPUT";
  242. current.inputs=readPrintList(readExpression);
  243. //NEXT
  244. break;case "NEXT":
  245. assert(currentBlock().type=="FOR","NEXT without FOR");
  246. readExpression();
  247. endBlock();
  248. //ON
  249. break;case "ON":
  250. current.type="ON"
  251. current.condition=readExpression();
  252. assert(readToken("GOTO")||readToken("GOSUB"),"ON without GOTO/GOSUB");
  253. current.onMode=""//GOTO or GOSUB
  254. assert(current.labels=readList(readExpression,true),"Missing label list after ON");
  255. //PRINT
  256. break;case "PRINT":
  257. current.type="PRINT"
  258. current.inputs=readPrintList(readExpression);
  259. //REM
  260. break;case "REM":
  261. do{
  262. next();
  263. }while(type!=="linebreak" && type!=="eof");;;
  264. //RETURN
  265. break;case "RETURN":
  266. current.type="RETURN";
  267. if(defType===2)
  268. current.value=readExpression();
  269. //OUT/THEN
  270. break;case "OUT":case "THEN":
  271. assert(false,"Illegal OUT/THEN");
  272. //other words
  273. break;case "word":case "(":
  274. //var name=text;
  275. readNext=readNext-1;
  276. var oldWord=word; //this is, the variable name! :D
  277. switch(readVariable(true)){
  278. case true:
  279. assert(readToken("="),"missing =");
  280. current.type="assignment";
  281. current.variableName=oldWord;
  282. current.value=readExpression();
  283. break;case false:
  284. alert("what");
  285. break;default:
  286. if(peekToken("=")){
  287. readToken("=");
  288. current.type="assignment";
  289. current.variableName=oldWord;
  290. current.value=readExpression();
  291. }else{
  292. //HORRIBLE STUPID FAKE KEYWORDS!!!
  293. //XON/XOFF/OPTION
  294. // I hate you! :(
  295. // not nice >:[
  296. switch(oldWord){
  297. case "XON":
  298. current.type="xon";
  299. if(readToken("word")){
  300. assert(word==="MOTION"||word==="EXPAD"||word==="MIC"||word==="WIIU"||word=="COMPAT","invalid option");
  301. current.feature=word;
  302. }else{
  303. //what the [heck] were you THINKING!?!??!
  304. assert(readToken("number"),"invalid option");
  305. assert(word==="3","invalid option");
  306. assert(readToken("word"),"invalid option");
  307. assert(word==="DS","invalid option");
  308. current.feature="3DS";
  309. }
  310. break;case "XOFF":
  311. current.type="xon";
  312. assert(readToken("word"));
  313. assert(word==="MOTION"||word==="EXPAD"||word==="MIC"||word=="COMPAT","invalid option");
  314. current.feature=word;
  315. break;case "OPTION":
  316. current.type="option";
  317. assert(readToken("word"),"invalid option");
  318. assert(word==="STRICT"||word==="DEFINT"||word==="TOOL","invalid option");
  319. current.option=word;
  320. //return to sanity, normal function call!
  321. break;default:
  322. current.type="function";
  323. current.inputs=readList(readExpression);
  324. if(readToken("OUT"))
  325. current.outputs=readList(readVariable);
  326. else
  327. current.outputs=[];
  328. }
  329. }
  330. }
  331. //label
  332. break;case "label":
  333. current.type="label";
  334. current.label=word; //TODO: store label names
  335. //comment
  336. break;case "comment":
  337. //end
  338. break;case "eof":
  339. //line break, colon
  340. break;case ":":
  341. break;case "linebreak":
  342. break;default:
  343. assert(false,"Expected statement, got "+type);
  344. }
  345. if(current.type){
  346. currentBlocks[currentBlocks.length-1].code.push(current)//push to current block!
  347. current={}
  348. }
  349. }
  350.  
  351. function currentBlock(){
  352. return currentBlocks[currentBlocks.length-1]
  353. }
  354.  
  355. //check if next token is of a specific type
  356. function peekToken(wantedType){
  357. var prevType=type,prevText=text,prevWord=word;
  358. next();
  359. readNext=-1;
  360. newType=type;
  361. newText=text;
  362. newWord=word;
  363. type=prevType;
  364. text=prevText;
  365. word=prevWord;
  366. return newType===wantedType;
  367. }
  368. //check if next token is of a specific type
  369. function peekWord(wantedWord){
  370. var prevType=type,prevText=text,prevWord=word;
  371. next();
  372. readNext=-1;
  373. newType=type;
  374. newText=text;
  375. newWord=word;
  376. type=prevType;
  377. text=prevText;
  378. word=prevWord;
  379. return newType==="word" && newWord.trimLeft().toUpperCase()===wantedWord;
  380. }
  381.  
  382. //Try to read a specific token
  383. function readToken(wantedType){
  384. next();
  385. if(type===wantedType){
  386. readNext=1;
  387. return true;
  388. }
  389. readNext=0;
  390. return false;
  391. }
  392.  
  393. //Read list
  394. //reader: function to read item (readExpression etc.)
  395. //noNull: throw an error if a null value is found
  396. function readList(reader,noNull){
  397. var ret=reader();
  398. if(readToken(",","")){
  399. assert(ret||!noNull,"Null value not allowed");
  400. ret=1;
  401. do{
  402. assert(reader()||!noNull,"Null value not allowed");
  403. }while(readToken(",",""));;;
  404. }
  405. return ret;
  406. }
  407.  
  408. //read list of PRINT arguments
  409. function readPrintList(reader){
  410. if(!reader())
  411. return;
  412. while((readToken(",","")||readToken(";",""))&&reader());
  413. }
  414.  
  415. //read normal expression
  416. //SHould return RPN list
  417. function readExpression(){
  418. readExpression2();
  419. return "[expression]";
  420. }
  421.  
  422. function readExpression2(){
  423. var ret=false;
  424. next();
  425. switch(type){
  426. //VAR()
  427. case "VAR":
  428. readVar();
  429. //function or variable
  430. break;case "word":
  431. if(peekToken("(")){
  432. output("function");
  433. readToken("(","");
  434. readList(readExpression);
  435. assert(readToken(")",""),"Missing \")\" in function call");
  436. }else
  437. output("variable");
  438. //CALL()
  439. break;case "CALL":
  440. if(peekToken("(")){
  441. output("function call");
  442. readToken("(","");
  443. readList(readExpression);
  444. assert(readToken(")",""),"Missing \")\" in CALL()");
  445. ret=true;
  446. //bad VAR
  447. }else{
  448. output("error");
  449. assert(false,"invalid CALL");
  450. }
  451. //literal value
  452. break;case "number":case "string":case "label":
  453. output(type);
  454. //operator (unary)
  455. break;case "unary":case "minus":
  456. output("operator");
  457. assert(readExpression(),"Missing operator argument");
  458. //open parenthesis
  459. break;case "(":
  460. output("");
  461. readExpression();
  462. assert(readToken(")",""),"Missing \")\"");
  463. //other crap
  464. break;default:
  465. readNext=0;
  466. return false;
  467. }
  468. //read []s
  469. while(readToken("[","")){
  470. assert(readList(readExpression,true),"Missing array index");
  471. assert(readToken("]",""),"Missing \"]\"");
  472. }
  473. //read infix operators
  474. while(readToken("operator","operator")||readToken("minus","operator"))
  475. assert(readExpression(),"Operator missing second argument");
  476. return true;
  477. }
  478.  
  479. //read function definition argument
  480. function readArgument(){
  481. if(readToken("word","variable")){
  482. if(readToken("[",""))
  483. assert(readToken("]",""),"Missing \"]\"");
  484. return true;
  485. }
  486. return false;
  487. }
  488.  
  489. //read variable declaration
  490. function readDeclaration(){
  491. if(readToken("word","variable")){
  492. if(readToken("[","")){
  493. assert(readList(readExpression,true),"Missing array size");
  494. assert(readToken("]",""),"Missing \"]\"");
  495. }else if(readToken("=",""))
  496. readExpression();
  497. return true;
  498. }
  499. return false;
  500. }
  501.  
  502. //read function VAR()
  503. function readVar(){
  504. //"function" form of VAR
  505. if(peekToken("(")){
  506. output("var function");
  507. readToken("(","");
  508. assert(readExpression(),"Missing VAR argument");
  509. assert(readToken(")",""),"Missing \")\" in VAR()");
  510. //bad VAR
  511. }else{
  512. output("error");
  513. assert(false,"invalid VAR");
  514. }
  515. }
  516.  
  517. //keys:
  518. //name: [variable name expr token list]
  519. //indexes: [index list]
  520. function readVariable(noPrintVarName){
  521. var ret={name:"",indexes:[]};
  522. next();
  523. switch(type){
  524. case "VAR":
  525. ret.name=readVar();
  526. break;case "word":
  527. ret.name=word;
  528. break;default:
  529. readNext=0;
  530. return false;
  531. }
  532. while(readToken("[")){
  533. assert(ret.indexes.push(readExpression()),"Missing index");
  534. assert(readToken("]"),"Missing \"]\"");
  535. }
  536. return ret;
  537. }
  538.  
  539. //throw error with message if condition is false
  540. function assert(condition,message){
  541. if(!condition){
  542. console.log(message);
  543. var error=new Error(message);
  544. error.name="ParseError";
  545. throw error;
  546. }
  547. }
  548.  
  549. function output(type){
  550. return;
  551. if(type==="function"){
  552. if(BUILTINS.indexOf(word)>=0)
  553. callback(text,"builtin function");
  554. else
  555. callback(text,type);
  556. }else if(type==="variable"){
  557. if(SYSTEMVARS.indexOf(word)>=0)
  558. callback(text,"builtin variable");
  559. else
  560. callback(text,type);
  561. }else
  562. callback(text,type);
  563. }
  564.  
  565. //I forgot how this works...
  566. function next(){
  567. if(readNext===1){
  568. var items=nextToken();
  569. type=items.type;
  570. text=items.text;
  571. word=items.word;
  572. }else if(readNext===-1){
  573. type=newType;
  574. text=newText;
  575. word=newWord;
  576. readNext=1;
  577. //I don't think this ever happens?
  578. }else if(readNext===-2)
  579. readNext=-1;
  580. else
  581. readNext=1;
  582. }
  583.  
  584. console.log(blocks,currentBlocks)
  585.  
  586. //if(currentBlocks.length)
  587. //return "unclosed thing";
  588. return currentBlocks;
  589. }
  590.  
  591. //TOKENIZER STREAM GENERATOR
  592. //input: code (string)
  593. //output: function that returns the next token when called
  594. function tokenize(code){
  595. var i=-1,c,isAlpha,isDigit,whitespace;
  596.  
  597. function next(){
  598. i++;
  599. c=code.charAt(i);
  600. //woah woah calm down don't worry I'm not some idiot who uses apostrophe strings...
  601. //These are single CHARACTERS (that is, in a language that has a char type, these should be chars and not strings)
  602. isAlpha=(c>='A'&&c<='Z'||c>='a'&&c<='z');
  603. isDigit=(c>='0'&&c<='9');
  604. }
  605.  
  606. function jump(pos){
  607. i=pos-1;
  608. next();
  609. }
  610.  
  611. var prev=0;
  612. function pushWord(){
  613. var start=prev;
  614. prev=i;
  615. var upper=code.substring(whitespace,i).toUpperCase();
  616. var type;
  617. //bitwise not
  618. if(upper==="NOT")
  619. type="unary";
  620. //word operators
  621. else if(upper==="DIV"||upper==="MOD"||upper==="AND"||upper==="OR"||upper==="XOR")
  622. type="operator";
  623. //true/false
  624. else if(upper==="TRUE"||upper==="FALSE")
  625. type="number";
  626. //other keyword
  627. else if(KEYWORDS.indexOf(upper)!==-1)
  628. type=upper;
  629. //not a keyword
  630. else
  631. type="word";
  632. return {type:type,text:code.substring(start,i),word:upper};
  633. }
  634.  
  635.  
  636. function push(type){
  637. var start=prev;
  638. prev=i;
  639. return {type:type,text:code.substring(start,i)};
  640. }
  641.  
  642. next();
  643. return function(){
  644. //read whitespace
  645. while(c===" "||c==="\t")
  646. next();
  647. //if this is the end, push a special ending token
  648. if(c==='')
  649. return push("eof");
  650. //store the start of the non-whitespace
  651. whitespace=i;
  652. //"word" (keywords, functions, variables)
  653. if(isAlpha||c==='_'){
  654. next();
  655. while(isAlpha||isDigit||c==='_')
  656. next();
  657. if(c==='#'||c==='%'||c==='$'){
  658. next();
  659. return push("word");
  660. }
  661. return pushWord();
  662. //numbers
  663. }else if(isDigit||c==='.'){
  664. while(isDigit)
  665. next();
  666. if(c==='.'){
  667. next();
  668. if(isDigit){
  669. next();
  670. while(isDigit)
  671. next();
  672. }else{
  673. if(c==='#')
  674. next();
  675. return push("number");
  676. }
  677. }
  678. if(c==='E'||c==='e'){
  679. var ePos=i;
  680. next();
  681. if(c==='+'||c==='-')
  682. next();
  683. if(isDigit){
  684. next();
  685. while(isDigit)
  686. next();
  687. }else{
  688. jump(ePos);
  689. return push("error");
  690. }
  691. }
  692. if(c==='#')
  693. next();
  694. return push("number");
  695. }else switch(c){
  696. //strings
  697. case '"':
  698. next();
  699. while(c && c!=='"' && c!=='\n' && c!=='\r')
  700. next();
  701. if(c==='"')
  702. next();
  703. return push("string");
  704. //comments
  705. break;case '\'':
  706. next();
  707. while(c && c!=='\n' && c!=='\r')
  708. next();
  709. return push("comment");
  710. //logical AND, hexadecimal, binary
  711. break;case '&':
  712. next();
  713. switch(c){
  714. case '&':
  715. next();
  716. return push("operator");
  717. break;case 'H':case 'h':
  718. var hPos=i;
  719. next();
  720. if(isDigit||c>='A'&&c<='F'||c>='a'&&c<='f'){
  721. next();
  722. while(isDigit||c>='A'&&c<='F'||c>='a'&&c<='f')
  723. next();
  724. return push("number");
  725. }
  726. jump(hPos);
  727. return push("error");
  728. break;case 'B':case 'b':
  729. var bPos=i;
  730. next();
  731. if(c==='0'||c==='1'){
  732. next();
  733. while(c==='0'||c==='1')
  734. next();
  735. return push("number");
  736. }
  737. jump(bPos);
  738. return push("error");
  739. break;default:
  740. return push("error");
  741. }
  742. //labels
  743. break;case '@':
  744. next();
  745. if(isDigit||isAlpha||c==="_"){
  746. next();
  747. while(isDigit||isAlpha||c==="_")
  748. next();
  749. return push("label");
  750. }
  751. return push("error");
  752. //constants
  753. break;case '#':
  754. next();
  755. if(isDigit||isAlpha){
  756. next();
  757. while(isDigit||isAlpha)
  758. next();
  759. return push("number");
  760. }
  761. return push("error");
  762. //logical or
  763. break;case '|':
  764. next();
  765. if(c==='|'){
  766. next();
  767. return push("operator");
  768. }
  769. return push("error");
  770. //less than, less than or equal, left shift
  771. break;case '<':
  772. next();
  773. if(c==='='||c==='<')
  774. next();
  775. return push("operator");
  776. //greater than, greater than or equal, right shift
  777. break;case '>':
  778. next();
  779. if(c==='='||c==='>')
  780. next();
  781. return push("operator");
  782. //equal, equal more
  783. break;case '=':
  784. next();
  785. if(c==='='){
  786. next();
  787. return push("operator");
  788. }
  789. return push("=");
  790. //logical not, not equal
  791. break;case '!':
  792. next();
  793. if(c==='='){
  794. next();
  795. return push("operator");
  796. }
  797. return push("unary");
  798. break;case '-':
  799. next();
  800. return push("minus");
  801. //add, subtract, multiply, divide
  802. break;case '+':case '*':case '/':
  803. next();
  804. return push("operator");
  805. //other
  806. break;case '\n':case '\r':
  807. next();
  808. return push("linebreak");
  809. //characters
  810. break;case '(':case ')':case '[':case ']':case ',':case ';':case ':':
  811. var chr=c;
  812. next();
  813. return push(chr);
  814. //print shortcut
  815. break;case '?':
  816. next();
  817. return push("PRINT");
  818. //other
  819. break;default:
  820. next();
  821. return push("text");
  822. }
  823. };
  824. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement