blob: dcbced435f15bda8dd1ffb9feca8f7af9c1e1992 [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.toml;
import java.lang.reflect.Field;
import org.antlr.v4.runtime.misc.IntegerStack;
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.tomlj.internal.TomlLexer.*;
import static org.netbeans.modules.languages.toml.TomlTokenId.*;
/**
*
* @author lkishalmi
*/
public final class TomlLexer implements Lexer<TomlTokenId> {
private final TokenFactory<TomlTokenId> tokenFactory;
private final org.tomlj.internal.TomlLexer lexer;
private final LexerInputCharStream input;
public TomlLexer(LexerRestartInfo<TomlTokenId> info) {
this.tokenFactory = info.tokenFactory();
this.input = new LexerInputCharStream(info.input());
this.lexer = new org.tomlj.internal.TomlLexer(input);
if (info.state() != null) {
((LexerState) info.state()).restore(lexer);
}
}
@Override
public Token<TomlTokenId> nextToken() {
org.antlr.v4.runtime.Token nextToken = lexer.nextToken();
if (nextToken.getType() == EOF) {
return null;
}
switch (nextToken.getType()) {
case TripleQuotationMark:
case TripleApostrophe:
return token(ML_STRING_START);
case StringChar:
case QuotationMark:
case Apostrophe:
return token(STRING);
case MLBasicStringEnd:
case MLLiteralStringEnd:
return token(ML_STRING_END);
case Comma:
case ArrayStart:
case ArrayEnd:
case InlineTableStart:
case InlineTableEnd:
case Dot:
return token(DOT);
case Equals:
return token(EQUALS);
case TableKeyStart:
case TableKeyEnd:
case ArrayTableKeyStart:
case ArrayTableKeyEnd:
return token(TABLE_MARK);
case UnquotedKey:
return token(KEY);
case Comment:
return token(COMMENT);
case WS:
case NewLine:
return token(TomlTokenId.WHITESPACE);
case Error:
return token(ERROR);
case DecimalInteger:
case HexInteger:
case OctalInteger:
case BinaryInteger:
case FloatingPoint:
case FloatingPointInf:
case FloatingPointNaN:
return token(NUMBER);
case TrueBoolean:
case FalseBoolean:
return token(BOOLEAN);
case EscapeSequence:
return token(ESCAPE_SEQUENCE);
case Dash:
case Plus:
case Colon:
case Z:
case TimeDelimiter:
case DateDigits:
case DateComma:
return token(DATE);
default:
return token(ERROR);
}
}
@Override
public Object state() {
return new LexerState(lexer);
}
@Override
public void release() {
}
private Token<TomlTokenId> token(TomlTokenId id) {
input.markToken();
return tokenFactory.createToken(id);
}
private static class LexerState {
private static Field ARRAY_DEPTH;
private static Field ARRAY_DEPTH_STACK;
final int state;
final int mode;
final IntegerStack modes;
final int arrayDepth;
final IntegerStack arrayDepthStack;
static {
try {
// Hack accessing private state parts of TomlLexer
// See: https://github.com/tomlj/tomlj/pull/42
ARRAY_DEPTH = org.tomlj.internal.TomlLexer.class.getDeclaredField("arrayDepth");
ARRAY_DEPTH.setAccessible(true);
ARRAY_DEPTH_STACK = org.tomlj.internal.TomlLexer.class.getDeclaredField("arrayDepthStack");
ARRAY_DEPTH_STACK.setAccessible(true);
} catch (ReflectiveOperationException ex) {
}
}
LexerState(org.tomlj.internal.TomlLexer lexer) {
this.state= lexer.getState();
this.mode = lexer._mode;
this.modes = new IntegerStack(lexer._modeStack);
try {
this.arrayDepth = ARRAY_DEPTH.getInt(lexer);
this.arrayDepthStack = new IntegerStack((IntegerStack)ARRAY_DEPTH_STACK.get(lexer));
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
public void restore(org.tomlj.internal.TomlLexer lexer) {
lexer.setState(state);
lexer._modeStack.addAll(modes);
lexer._mode = mode;
try {
ARRAY_DEPTH.setInt(lexer, arrayDepth);
((IntegerStack) ARRAY_DEPTH_STACK.get(lexer)).addAll(arrayDepthStack);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
@Override
public String toString() {
return String.valueOf(state);
}
}
}