blob: b7a59dabd14d9207395815e84954f40cfc90faee [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.languages.antlr;
import org.antlr.v4.runtime.misc.IntegerList;
import org.netbeans.api.lexer.Token;
import org.netbeans.spi.lexer.Lexer;
import org.netbeans.spi.lexer.LexerRestartInfo;
import org.netbeans.spi.lexer.TokenFactory;
import static org.antlr.parser.antlr4.ANTLRv4Lexer.*;
import static org.netbeans.modules.languages.antlr.AntlrTokenId.*;
/**
*
* @author lkishalmi
*/
public final class AntlrLexer implements Lexer<AntlrTokenId> {
private final TokenFactory<AntlrTokenId> tokenFactory;
private org.antlr.parser.antlr4.ANTLRv4Lexer lexer;
private final LexerInputCharStream input;
public AntlrLexer(LexerRestartInfo<AntlrTokenId> info) {
this.tokenFactory = info.tokenFactory();
this.input = new LexerInputCharStream(info.input());
this.lexer = new org.antlr.parser.antlr4.ANTLRv4Lexer(input);
if (info.state() != null) {
((LexerState) info.state()).restore(lexer);
}
input.markToken();
}
private org.antlr.v4.runtime.Token preFetchedToken = null;
@Override
public Token<AntlrTokenId> nextToken() {
org.antlr.v4.runtime.Token nextToken;
if (preFetchedToken != null) {
nextToken = preFetchedToken;
lexer.getInputStream().seek(preFetchedToken.getStopIndex() + 1);
preFetchedToken = null;
} else {
nextToken = lexer.nextToken();
}
if (nextToken.getType() == EOF) {
return null;
}
switch (nextToken.getType()) {
case TOKEN_REF:
return token(TOKEN);
case RULE_REF:
return token(RULE);
case DOC_COMMENT:
case BLOCK_COMMENT:
case LINE_COMMENT:
return token(AntlrTokenId.COMMENT);
case INT:
return token(NUMBER);
case LEXER_CHAR_SET:
case STRING_LITERAL:
case UNTERMINATED_STRING_LITERAL:
return token(STRING);
case OPTIONS:
case TOKENS:
case CHANNELS:
case IMPORT:
case FRAGMENT:
case LEXER:
case PARSER:
case GRAMMAR:
case PROTECTED:
case PUBLIC:
case PRIVATE:
case RETURNS:
case LOCALS:
case THROWS:
case CATCH:
case FINALLY:
case MODE:
return token(KEYWORD);
case COLON:
case COLONCOLON:
case LT:
case GT:
case BEGIN_ACTION:
case END_ACTION:
case AT:
case PLUS_ASSIGN:
case POUND:
case LBRACE:
case RBRACE:
case RARROW:
case ASSIGN:
case COMMA:
case SEMI:
return token(PUNCTUATION);
case LPAREN:
case RPAREN:
case QUESTION:
case STAR:
case PLUS:
case OR:
case DOLLAR:
case RANGE:
case DOT:
case NOT:
return token(REGEXP_CHARS);
case WS:
return token(WHITESPACE);
case ACTION_CONTENT:
preFetchedToken = lexer.nextToken();
while (preFetchedToken.getType() == ACTION_CONTENT) {
preFetchedToken = lexer.nextToken();
}
lexer.getInputStream().seek(preFetchedToken.getStartIndex());
return token(ACTION);
default:
return token(ERROR);
}
}
@Override
public Object state() {
return new LexerState(lexer);
}
@Override
public void release() {
}
private Token<AntlrTokenId> token(AntlrTokenId id) {
input.markToken();
return tokenFactory.createToken(id);
}
private static class LexerState {
final int state;
final int mode;
final IntegerList modes;
LexerState(org.antlr.v4.runtime.Lexer lexer) {
this.state= lexer.getState();
this.mode = lexer._mode;
this.modes = new IntegerList(lexer._modeStack);
}
public void restore(org.antlr.v4.runtime.Lexer lexer) {
lexer.setState(state);
lexer._modeStack.addAll(modes);
lexer._mode = mode;
}
@Override
public String toString() {
return String.valueOf(state);
}
}
}