Fantasy 8Bit system (F8), is a fantasy 8bit console and a set of libraries for creating fantasy 8bit consoles.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

193 lines
3.5KB

  1. function GetTextStream(input){
  2. var pos = 0;
  3. var line = 0;
  4. var col = 0;
  5. function peek(){
  6. return input.getChar(pos);
  7. }
  8. function next(){
  9. let c = input.charAt(pos);
  10. pos += 1;
  11. if (c === "\n"){
  12. line += 1;
  13. col = 0;
  14. } else {col += 1;}
  15. return c;
  16. }
  17. function eof(){
  18. return (input.charAt(pos) === "");
  19. }
  20. function die(msg){
  21. throw new Error(msg + " Line: " + line + ", Col: " + col);
  22. }
  23. return {
  24. peek: peek,
  25. get: next,
  26. eof: eof
  27. };
  28. }
  29. // ----------------------------------------------
  30. // VALIDATORS
  31. // ----------------------------------------------
  32. function isWhiteSpace(c){
  33. return ("\t\n ".indexOf(c) >= 0);
  34. }
  35. function isStringStart(c){
  36. return (c === "\"" || c === "'");
  37. }
  38. function isNumType(c){
  39. return ("$%".indexOf(c) >= 0 || isDigit(c));
  40. }
  41. function isDigit(c){
  42. return /[0-9]/i.test(c);
  43. }
  44. function isHex(c){
  45. return /[0-9a-fA-F]/i.test(c);
  46. }
  47. function isBinary(c){
  48. return ("01".indexOf(c) >= 0);
  49. }
  50. function isLabelStart(c){
  51. return /[a-fA-F_]/i.test(c);
  52. }
  53. function isLabel(c){
  54. return (isLabelStart(c) || isDigit(c));
  55. }
  56. function isPunctuation(c){
  57. return (",()".indexOf(c) >= 0);
  58. }
  59. function isOp(c){
  60. return ("=+-/*".indexOf(c) >= 0);
  61. }
  62. // ----------------------------------------------
  63. // Read Operations
  64. // ----------------------------------------------
  65. function skipComment(stream){
  66. readWhile(stream, (c)=>{return c != "\n";});
  67. stream.next();
  68. }
  69. function readHex(stream){
  70. stream.next();
  71. var str = readWhile(stream, isHex);
  72. return {type:'number', val: parseInt(str, 16)};
  73. }
  74. function readBinary(stream){
  75. stream.next();
  76. var str = readWhile(stream, isBinary);
  77. return {type:'number', val: parseInt(str, 2)};
  78. }
  79. function readNumber(stream){
  80. let c = stream.peek();
  81. if (c === "$")
  82. return readHex(stream);
  83. if (c === "%")
  84. return readBinary(stream);
  85. var dot = false;
  86. var str = readWhile(stream, (c)=>{
  87. if (c === "."){
  88. if (dot){return false;}
  89. dot = true;
  90. return true;
  91. }
  92. return isDigit(c);
  93. });
  94. return {type:'number', val:parseFloat(str)};
  95. }
  96. function readString(stream, end){
  97. var str = "";
  98. var escaped = false;
  99. stream.next();
  100. while (!stream.eof()){
  101. let c = stream.next();
  102. if (escaped){
  103. str += c;
  104. escaped = false;
  105. } else if (c === "\\"){
  106. escaped = true;
  107. } else if (c === end){
  108. break;
  109. } else {
  110. str += c;
  111. }
  112. }
  113. return {type: "string", val: str};
  114. }
  115. function readLabel(stream){
  116. str = readWhile(stream, isLabel);
  117. return {type:"label", val: str};
  118. }
  119. function readWhile(stream, validator){
  120. var str = "";
  121. while (!stream.eof() && validator(stream.peek()))
  122. str += stream.next();
  123. return str;
  124. }
  125. function nextToken(stream){
  126. readWhile(stream, isWhiteSpace);
  127. if (stream.eof()){return null;}
  128. let c = stream.peek();
  129. if (c === ";"){
  130. skipComment(stream);
  131. return nextToken(stream);
  132. } else if (isStringStart(c)){
  133. return readString(stream, c);
  134. } else if (isNumType(c)){
  135. return readNumber(stream);
  136. } else if (isLabelStart(c)){
  137. return readLabel(stream);
  138. } else if (isPunctuation(c)){
  139. return {type:"punctuation", val:stream.next()};
  140. } else if (isMathOp(c)){
  141. return {type:"op", val:stream.next()};
  142. }
  143. stream.die("Unable to process character '" + c + "'.");
  144. }
  145. function tokenize(input){
  146. var stream = GetTextStream(input);
  147. var tokens = [];
  148. var t = nextToken(stream);
  149. while (t !== null){
  150. tokens.push(t);
  151. t = nextToken(stream);
  152. }
  153. return tokens;
  154. }
  155. module.exports = tokenize;