UNPKG

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