util.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _index = require('../tokenizer/index');
  2. var _types = require('../tokenizer/types');
  3. var _charcodes = require('../util/charcodes');
  4. var _base = require('./base');
  5. // ## Parser utilities
  6. // Tests whether parsed token is a contextual keyword.
  7. function isContextual(contextualKeyword) {
  8. return _base.state.contextualKeyword === contextualKeyword;
  9. } exports.isContextual = isContextual;
  10. function isLookaheadContextual(contextualKeyword) {
  11. const l = _index.lookaheadTypeAndKeyword.call(void 0, );
  12. return l.type === _types.TokenType.name && l.contextualKeyword === contextualKeyword;
  13. } exports.isLookaheadContextual = isLookaheadContextual;
  14. // Consumes contextual keyword if possible.
  15. function eatContextual(contextualKeyword) {
  16. return _base.state.contextualKeyword === contextualKeyword && _index.eat.call(void 0, _types.TokenType.name);
  17. } exports.eatContextual = eatContextual;
  18. // Asserts that following token is given contextual keyword.
  19. function expectContextual(contextualKeyword) {
  20. if (!eatContextual(contextualKeyword)) {
  21. unexpected();
  22. }
  23. } exports.expectContextual = expectContextual;
  24. // Test whether a semicolon can be inserted at the current position.
  25. function canInsertSemicolon() {
  26. return _index.match.call(void 0, _types.TokenType.eof) || _index.match.call(void 0, _types.TokenType.braceR) || hasPrecedingLineBreak();
  27. } exports.canInsertSemicolon = canInsertSemicolon;
  28. function hasPrecedingLineBreak() {
  29. const prevToken = _base.state.tokens[_base.state.tokens.length - 1];
  30. const lastTokEnd = prevToken ? prevToken.end : 0;
  31. for (let i = lastTokEnd; i < _base.state.start; i++) {
  32. const code = _base.input.charCodeAt(i);
  33. if (
  34. code === _charcodes.charCodes.lineFeed ||
  35. code === _charcodes.charCodes.carriageReturn ||
  36. code === 0x2028 ||
  37. code === 0x2029
  38. ) {
  39. return true;
  40. }
  41. }
  42. return false;
  43. } exports.hasPrecedingLineBreak = hasPrecedingLineBreak;
  44. function hasFollowingLineBreak() {
  45. const nextStart = _index.nextTokenStart.call(void 0, );
  46. for (let i = _base.state.end; i < nextStart; i++) {
  47. const code = _base.input.charCodeAt(i);
  48. if (
  49. code === _charcodes.charCodes.lineFeed ||
  50. code === _charcodes.charCodes.carriageReturn ||
  51. code === 0x2028 ||
  52. code === 0x2029
  53. ) {
  54. return true;
  55. }
  56. }
  57. return false;
  58. } exports.hasFollowingLineBreak = hasFollowingLineBreak;
  59. function isLineTerminator() {
  60. return _index.eat.call(void 0, _types.TokenType.semi) || canInsertSemicolon();
  61. } exports.isLineTerminator = isLineTerminator;
  62. // Consume a semicolon, or, failing that, see if we are allowed to
  63. // pretend that there is a semicolon at this position.
  64. function semicolon() {
  65. if (!isLineTerminator()) {
  66. unexpected('Unexpected token, expected ";"');
  67. }
  68. } exports.semicolon = semicolon;
  69. // Expect a token of a given type. If found, consume it, otherwise,
  70. // raise an unexpected token error at given pos.
  71. function expect(type) {
  72. const matched = _index.eat.call(void 0, type);
  73. if (!matched) {
  74. unexpected(`Unexpected token, expected "${_types.formatTokenType.call(void 0, type)}"`);
  75. }
  76. } exports.expect = expect;
  77. /**
  78. * Transition the parser to an error state. All code needs to be written to naturally unwind in this
  79. * state, which allows us to backtrack without exceptions and without error plumbing everywhere.
  80. */
  81. function unexpected(message = "Unexpected token", pos = _base.state.start) {
  82. if (_base.state.error) {
  83. return;
  84. }
  85. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  86. const err = new SyntaxError(message);
  87. err.pos = pos;
  88. _base.state.error = err;
  89. _base.state.pos = _base.input.length;
  90. _index.finishToken.call(void 0, _types.TokenType.eof);
  91. } exports.unexpected = unexpected;