lexer.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. "use strict";
  2. var Errors = require("errors.js");
  3. var Stream = require("oberon.js/Stream.js");
  4. function isDigit(c) {return c >= '0' && c <= '9';}
  5. exports.digit = function(stream, context){
  6. if (Stream.eof(stream))
  7. return false;
  8. var c = Stream.getChar(stream);
  9. if (!isDigit(c))
  10. return false;
  11. context.handleChar(c);
  12. return true;
  13. };
  14. exports.hexDigit = function(stream, context){
  15. var c = Stream.getChar(stream);
  16. if (!isDigit(c) && (c < 'A' || c > 'F'))
  17. return false;
  18. context.handleChar(c);
  19. return true;
  20. };
  21. exports.point = function(stream, context){
  22. if (Stream.eof(stream)
  23. || Stream.getChar(stream) != '.'
  24. || (!Stream.eof(stream) && Stream.peekChar(stream) == '.')) // not a diapason ".."
  25. return false;
  26. context.handleLiteral(".");
  27. return true;
  28. };
  29. exports.character = function(stream, context){
  30. var c = stream.getChar();
  31. if (c == '"')
  32. return false;
  33. context.handleChar(c);
  34. return true;
  35. };
  36. function string(stream, context){
  37. if (Stream.eof(stream))
  38. return false;
  39. var c = Stream.getChar(stream);
  40. if (c != '"')
  41. return false;
  42. var result = "";
  43. var parsed = false;
  44. Stream.read(stream, function(c){
  45. if (c == '"'){
  46. parsed = true;
  47. return false;
  48. }
  49. result += c;
  50. return true;
  51. });
  52. if (!parsed)
  53. throw new Errors.Error("unexpected end of string");
  54. Stream.next(stream, 1);
  55. context.handleString(result);
  56. return true;
  57. }
  58. function isLetter(c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');}
  59. var reservedWords
  60. = ["ARRAY", "IMPORT", "THEN", "BEGIN", "IN", "TO", "BY", "IS",
  61. "TRUE", "CASE", "MOD", "TYPE", "CONST", "MODULE", "UNTIL", "DIV",
  62. "NIL", "VAR", "DO", "OF", "WHILE", "ELSE", "OR", "ELSIF", "POINTER",
  63. "END", "PROCEDURE", "FALSE", "RECORD", "FOR", "REPEAT", "IF", "RETURN"
  64. ];
  65. var jsReservedWords
  66. = ["break", "case", "catch", "continue", "debugger", "default", "delete",
  67. "do", "else", "finally", "for", "function", "if", "in", "instanceof",
  68. "new", "return", "switch", "this", "throw", "try", "typeof", "var",
  69. "void", "while", "with",
  70. "Math" // Math is used in generated code for some functions so it is reserved word from code generator standpoint
  71. ];
  72. exports.ident = function(stream, context){
  73. if (Stream.eof(stream) || !isLetter(Stream.peekChar(stream)))
  74. return false;
  75. var savePos = Stream.pos(stream);
  76. var result = "";
  77. Stream.read(stream, function(c){
  78. if (!isLetter(c) && !isDigit(c) /*&& c != '_'*/)
  79. return false;
  80. result += c;
  81. return true;
  82. });
  83. if (reservedWords.indexOf(result) != -1){
  84. Stream.setPos(stream, savePos);
  85. return false;
  86. }
  87. if (jsReservedWords.indexOf(result) != -1)
  88. result += "$";
  89. context.setIdent(result);
  90. return true;
  91. };
  92. function skipComment(stream){
  93. if (Stream.peekStr(stream, 2) != "(*")
  94. return false;
  95. Stream.next(stream, 2);
  96. while (Stream.peekStr(stream, 2) != "*)"){
  97. if (Stream.eof(stream))
  98. throw new Errors.Error("comment was not closed");
  99. if (!skipComment(stream))
  100. Stream.next(stream, 1);
  101. }
  102. Stream.next(stream, 2);
  103. return true;
  104. }
  105. function readSpaces(c){return ' \t\n\r'.indexOf(c) != -1;}
  106. exports.skipSpaces = function(stream, context){
  107. if (context && context.isLexem && context.isLexem())
  108. return;
  109. do {
  110. Stream.read(stream, readSpaces);
  111. }
  112. while (skipComment(stream));
  113. };
  114. exports.separator = function(stream, context){
  115. return Stream.eof(stream) || !isLetter(Stream.peekChar(stream));
  116. };
  117. exports.literal = function(s){
  118. return function(stream, context){
  119. if (Stream.peekStr(stream, s.length) != s)
  120. return false;
  121. Stream.next(stream, s.length);
  122. if ((!context.isLexem || !context.isLexem())
  123. && isLetter(s[s.length - 1])
  124. && !Stream.eof(stream)
  125. ){
  126. var next = Stream.peekChar(stream);
  127. if (isLetter(next) || isDigit(next))
  128. return false;
  129. }
  130. var result = context.handleLiteral(s);
  131. return result === undefined || result;
  132. };
  133. };
  134. exports.string = string;