lexer.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. var Errors = require("errors.js");
  2. function isDigit(c) {return c >= '0' && c <= '9';}
  3. exports.digit = function(stream, context){
  4. var c = stream.char();
  5. if (!isDigit(c))
  6. return false;
  7. context.handleChar(c);
  8. return true;
  9. }
  10. exports.hexDigit = function(stream, context){
  11. var c = stream.char();
  12. if (!isDigit(c) && (c < 'A' || c > 'F'))
  13. return false;
  14. context.handleChar(c);
  15. return true;
  16. }
  17. exports.point = function(stream, context){
  18. if (stream.char() != '.'
  19. || stream.peekChar() == '.') // not a diapason ".."
  20. return false;
  21. context.handleLiteral(".");
  22. return true;
  23. }
  24. exports.character = function(stream, context){
  25. var c = stream.char();
  26. if (c == '"')
  27. return false;
  28. context.handleChar(c);
  29. return true;
  30. }
  31. function isLetter(c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');}
  32. exports.ident = function(stream, context){
  33. if (!isLetter(stream.peekChar()))
  34. return false;
  35. var savePos = stream.pos();
  36. var result = "";
  37. stream.read(function(c){
  38. if (!isLetter(c) && !isDigit(c) /*&& c != '_'*/)
  39. return false;
  40. result += c;
  41. return true;
  42. });
  43. var keywords = ["ARRAY", "END", "VAR", "TYPE", "IF", "CASE", "WHILE", "REPEAT", "FOR", "NIL", "TRUE", "FALSE", "IS"];
  44. if (keywords.indexOf(result) != -1){
  45. stream.setPos(savePos);
  46. return false;
  47. }
  48. context.setIdent(result);
  49. return true;
  50. }
  51. function skipComment(stream){
  52. if (stream.peekStr(2) != "(*")
  53. return false;
  54. stream.next(2);
  55. while (stream.peekStr(2) != "*)"){
  56. if (stream.eof())
  57. throw new Errors.Error("comment was not closed");
  58. if (!skipComment(stream))
  59. stream.next(1);
  60. }
  61. stream.next(2);
  62. return true;
  63. }
  64. exports.skipSpaces = function(stream, context){
  65. if (context.isLexem && context.isLexem())
  66. return;
  67. stream.read(function(c){return ' \t\n\r'.indexOf(c) != -1;});
  68. skipComment(stream);
  69. }
  70. exports.separator = function(stream, context){
  71. return !isLetter(stream.peekChar());
  72. }
  73. exports.literal = function(s){
  74. return function(stream, context){
  75. if (stream.str(s.length) != s)
  76. return false;
  77. stream.next(s.length);
  78. if ((!context.isLexem || !context.isLexem()) && isLetter(s[s.length - 1])){
  79. var next = stream.peekChar();
  80. if (isLetter(next) || isDigit(next))
  81. return false;
  82. }
  83. context.handleLiteral(s);
  84. return true;
  85. }
  86. }