public Parser( Config config, ErrorReporter errorReporter, SourceFile source, int offset, boolean initialGeneratorContext) { this.config = config; this.errorReporter = errorReporter; this.scanner = new Scanner(config.parseTypeSyntax, errorReporter, commentRecorder, source, offset); this.functionContextStack.addLast( initialGeneratorContext ? FunctionFlavor.GENERATOR : FunctionFlavor.NORMAL); lastSourcePosition = scanner.getPosition(); }
public LiteralToken nextRegularExpressionLiteralToken() { clearTokenLookahead(); int beginToken = index; // leading '/' nextChar(); // body if (!skipRegularExpressionBody()) { return new LiteralToken( TokenType.REGULAR_EXPRESSION, getTokenString(beginToken), getTokenRange(beginToken)); } // separating '/' if (peekChar() != '/') { reportError("Expected '/' in regular expression literal"); return new LiteralToken( TokenType.REGULAR_EXPRESSION, getTokenString(beginToken), getTokenRange(beginToken)); } nextChar(); // flags while (isIdentifierPart(peekChar())) { nextChar(); } return new LiteralToken( TokenType.REGULAR_EXPRESSION, getTokenString(beginToken), getTokenRange(beginToken)); }
private LineNumberTable getLineNumberTable() { return this.getFile().lineNumberTable; }
public TemplateLiteralToken nextTemplateLiteralToken() { Token token = nextToken(); if (isAtEnd() || token.type != TokenType.CLOSE_CURLY) { reportError(getPosition(index), "Expected '}' after expression in template literal"); } return nextTemplateLiteralTokenShared(TokenType.TEMPLATE_TAIL, TokenType.TEMPLATE_MIDDLE); }
public SourcePosition getPosition() { return getPosition(getOffset()); }
private void reportError(String format, Object... arguments) { reportError(getPosition(), format, arguments); }
private Token scanPostZero(int beginToken) { switch (peekChar()) { case 'b': case 'B': nextChar(); if (!isBinaryDigit(peekChar())) { reportError("Binary Integer Literal must contain at least one digit"); skipBinaryDigits(); return new LiteralToken( TokenType.NUMBER, getTokenString(beginToken), getTokenRange(beginToken)); nextChar(); if (!isOctalDigit(peekChar())) { reportError("Octal Integer Literal must contain at least one digit"); skipOctalDigits(); if (peek('8') || peek('9')) { reportError("Invalid octal digit in octal literal."); TokenType.NUMBER, getTokenString(beginToken), getTokenRange(beginToken)); case 'x': case 'X': nextChar(); if (!peekHexDigit()) { reportError("Hex Integer Literal must contain at least one digit"); skipHexDigits(); return new LiteralToken(
private Token scanToken() { skipComments(); int beginToken = index; if (isAtEnd()) { return createToken(TokenType.END_OF_FILE, beginToken); char ch = nextChar(); switch (ch) { case '{': return createToken(TokenType.OPEN_CURLY, beginToken); case '}': return createToken(TokenType.CLOSE_CURLY, beginToken); case '(': return createToken(TokenType.OPEN_PAREN, beginToken); case ')': return createToken(TokenType.CLOSE_PAREN, beginToken); case '[': return createToken(TokenType.OPEN_SQUARE, beginToken); case ']': return createToken(TokenType.CLOSE_SQUARE, beginToken); case '.': if (isDecimalDigit(peekChar())) { return scanNumberPostPeriod(beginToken); if (peek('.') && peekChar(1) == '.') { nextChar(); nextChar(); return createToken(TokenType.SPREAD, beginToken); return createToken(TokenType.PERIOD, beginToken); case ';': return createToken(TokenType.SEMI_COLON, beginToken); case ',': return createToken(TokenType.COMMA, beginToken); case '~': return createToken(TokenType.TILDE, beginToken); case '?': return createToken(TokenType.QUESTION, beginToken); case ':': return createToken(TokenType.COLON, beginToken); case '<':
int unicodeEscapeLen = containsUnicodeEscape ? 1 : 0; ch = peekChar(); while (isIdentifierPart(ch) || ch == '\\' || (ch == '{' && unicodeEscapeLen == 2) valueBuilder.append(nextChar()); ch = peekChar(); value = processUnicodeEscapes(value); if (value == null) { reportError( getPosition(index), "Invalid escape sequence"); return createToken(TokenType.ERROR, beginToken); if (!isIdentifierStart(start)) { reportError( getPosition(beginToken), "Character '%c' (U+%04X) is not a valid identifier start char", start, (int) start); return createToken(TokenType.ERROR, beginToken); return new Token(k.type, getTokenRange(beginToken)); return new IdentifierToken(getTokenRange(beginToken), value);
private Token scanStringLiteral(int beginIndex, char terminator) { while (peekStringLiteralChar(terminator)) { if (!skipStringLiteralChar()) { return new LiteralToken( TokenType.STRING, getTokenString(beginIndex), getTokenRange(beginIndex)); } } if (peekChar() != terminator) { reportError(getPosition(beginIndex), "Unterminated string literal"); } else { nextChar(); } return new LiteralToken( TokenType.STRING, getTokenString(beginIndex), getTokenRange(beginIndex)); }
private LiteralToken nextTemplateLiteralTokenShared(TokenType endType, TokenType middleType) { int beginIndex = index; skipTemplateCharacters(); if (isAtEnd()) { reportError(getPosition(beginIndex), "Unterminated template literal"); } String value = getTokenString(beginIndex); switch (peekChar()) { case '`': nextChar(); return new LiteralToken(endType, value, getTokenRange(beginIndex - 1)); case '$': nextChar(); // $ nextChar(); // { return new LiteralToken(middleType, value, getTokenRange(beginIndex - 1)); default: // Should have reported error already return new LiteralToken(endType, value, getTokenRange(beginIndex - 1)); } }
private LiteralToken scanExponentOfNumericLiteral(int beginToken) { switch (peekChar()) { case 'e': case 'E': nextChar(); switch (peekChar()) { case '+': case '-': nextChar(); break; default: // fall out } if (!isDecimalDigit(peekChar())) { reportError("Exponent part must contain at least one digit"); } skipDecimalDigits(); break; default: break; } return new LiteralToken( TokenType.NUMBER, getTokenString(beginToken), getTokenRange(beginToken)); }
private void skipSingleLineComment(Comment.Type type) { int startOffset = index; while (!isAtEnd() && !isLineTerminator(peekChar())) { nextChar(); } SourceRange range = getLineNumberTable().getSourceRange(startOffset, index); String value = this.contents.substring(startOffset, index); recordComment(type, range, value); }
private void skipMultiLineComment() { int startOffset = index; nextChar(); // '/' nextChar(); // '*' while (!isAtEnd() && (peekChar() != '*' || peekChar(1) != '/')) { nextChar(); } if (!isAtEnd()) { nextChar(); nextChar(); Comment.Type type = (index - startOffset > 4 && this.source.contents.charAt(startOffset + 2) == '*') ? Comment.Type.JSDOC : Comment.Type.BLOCK; SourceRange range = getLineNumberTable().getSourceRange( startOffset, index); String value = this.source.contents.substring( startOffset, index); recordComment(type, range, value); } else { reportError("unterminated comment"); } }
private ParseTree parseTypeArgumentList(SourcePosition start, TypeNameTree typeName) { // < TypeArgumentList > // TypeArgumentList , TypeArgument eat(TokenType.OPEN_ANGLE); scanner.incTypeParameterLevel(); ImmutableList.Builder<ParseTree> typeArguments = ImmutableList.builder(); ParseTree type = parseType(); typeArguments.add(type); while (peek(TokenType.COMMA)) { eat(TokenType.COMMA); type = parseType(); if (type != null) { typeArguments.add(type); } } eat(TokenType.CLOSE_ANGLE); scanner.decTypeParameterLevel(); return new ParameterizedTypeTree(getTreeLocation(start), typeName, typeArguments.build()); }
/** * Forks the parser at the current point and returns a new * parser for speculative parsing. * * @deprecated Creating a lookahead parser often leads to exponential parse times * (see issues #1049, #1115, and #1148 on github) so avoid using this if possible. */ @Deprecated private Parser createLookaheadParser() { return new Parser(config, new LookaheadErrorReporter(), this.scanner.getFile(), this.scanner.getOffset(), inGeneratorContext()); }
/** * Reports an error at the current location. * @param message The message to report in String.format style. * @param arguments The arguments to fill in the message format. */ private void reportError(String message, Object... arguments) { errorReporter.reportError(scanner.getPosition(), message, arguments); } }
private SourceRange getTokenRange(int startOffset) { return getLineNumberTable().getSourceRange(startOffset, index); }
private void clearTokenLookahead() { index = getOffset(); currentTokens.clear(); }
private Token createToken(TokenType type, int beginToken) { return new Token(type, getTokenRange(beginToken)); }