You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lex.mjs 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. export default (source) => {
  2. let index = 0;
  3. const tokens = [];
  4. while (index < source.length) {
  5. const token = source[index];
  6. index += 1;
  7. switch (token) {
  8. case ' ':
  9. case '\t':
  10. case '\n':
  11. case '\r':
  12. break;
  13. case "~":
  14. case "+":
  15. case "-":
  16. case "*":
  17. case "/":
  18. case "^": {
  19. const op =
  20. token === "~" ? "invert" :
  21. token === "+" ? "add" :
  22. token === "-" ? "subtract" :
  23. token === "*" ? "multiply" :
  24. token === "/" ? "divide" :
  25. token === "^" ? "exponent" :
  26. null;
  27. tokens.push({
  28. kind: "operator",
  29. value: op,
  30. });
  31. break
  32. }
  33. case "(": {
  34. tokens.push({
  35. kind: "open-paren",
  36. });
  37. break;
  38. }
  39. case ")": {
  40. tokens.push({
  41. kind: "close-paren",
  42. });
  43. break;
  44. }
  45. default: {
  46. if (token.match(/^[0-9\.]$/)) {
  47. let currentToken = token;
  48. while (index < source.length && source[index].match(/^[0-9\.]$/)) {
  49. currentToken += source[index];
  50. index += 1;
  51. }
  52. const value = Number(currentToken);
  53. tokens.push({
  54. kind: "number",
  55. value,
  56. });
  57. break;
  58. }
  59. if (token.match(/^[a-z]$/)) {
  60. let currentToken = token;
  61. while (index < source.length && source[index].match(/^[a-z0-9_]$/)) {
  62. currentToken += source[index];
  63. index += 1;
  64. }
  65. tokens.push({
  66. kind: "variable",
  67. value: currentToken,
  68. });
  69. break;
  70. }
  71. throw new Error(`Syntax error: Unexpected "${token}"`)
  72. }
  73. }
  74. }
  75. return tokens;
  76. }