/*
* Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.antlr.works.editor.antlr4.highlighting;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
import org.antlr.netbeans.editor.text.OffsetRegion;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;
import org.openide.text.NbDocument;
/**
*
* @author Sam Harwell
*/
public class DocumentCharStreamV4 implements CharStream {
// -J-Dorg.antlr.works.editor.antlr4.highlighting.DocumentCharStreamV4.level=FINE
private static final Logger LOGGER = Logger.getLogger(DocumentCharStreamV4.class.getName());
private boolean explicitCache;
private int currentSnapshotLineStartIndex;
private String currentSnapshotLine;
private final StyledDocument document;
private int index;
public DocumentCharStreamV4(StyledDocument document) {
this.document = document;
//updateCachedLine();
}
public DocumentCharStreamV4(StyledDocument document, OffsetRegion cachedSpan) throws BadLocationException {
this.document = document;
this.explicitCache = true;
this.currentSnapshotLineStartIndex = cachedSpan.getStart();
this.currentSnapshotLine = document.getText(cachedSpan.getStart(), cachedSpan.getLength()).toString();
}
@Override
public String getText(Interval interval) {
int startIndex = interval.a;
int endIndexInclusive = interval.b;
if (currentSnapshotLine != null) {
if (startIndex >= currentSnapshotLineStartIndex && (endIndexInclusive + 1) <= currentSnapshotLineStartIndex + currentSnapshotLine.length()) {
return currentSnapshotLine.substring(startIndex - currentSnapshotLineStartIndex, endIndexInclusive - currentSnapshotLineStartIndex + 1);
}
}
try {
return document.getText(startIndex, endIndexInclusive - startIndex + 1).toString();
} catch (BadLocationException ex) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
return null;
}
}
@Override
public void consume() {
int la = LA(1);
if (la < 0)
return;
index++;
updateCachedLine();
}
@Override
public int LA(int i) {
if (i == 0) {
// undefined
return 0;
}
if (i < 0) {
// e.g. translate LA(-1) to use offset i=0, then data[p+0-1]
i++;
if ((index() + i - 1) < 0) {
// invalid; no char before first char
return Token.EOF;
}
}
if ((index() + i - 1) >= size()) {
return Token.EOF;
}
int actualIndex = index() + i - 1;
if (currentSnapshotLine != null
&& actualIndex >= currentSnapshotLineStartIndex
&& actualIndex < currentSnapshotLineStartIndex + currentSnapshotLine.length()) {
return currentSnapshotLine.charAt(actualIndex - currentSnapshotLineStartIndex);
}
try {
return document.getText(actualIndex, 1).charAt(0);
} catch (BadLocationException ex) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
return Token.EOF;
}
}
@Override
public int mark() {
return 0;
}
@Override
public int index() {
return index;
}
@Override
public void release(int marker) {
}
@Override
public void seek(int index) {
if (this.index() == index) {
return;
}
this.index = index;
updateCachedLine();
}
@Override
public int size() {
return document.getLength();
}
@Override
public String getSourceName() {
return "NbEditor";
}
private void updateCachedLine() {
if (explicitCache)
return;
if (currentSnapshotLine == null
|| index() < currentSnapshotLineStartIndex
|| index() >= currentSnapshotLineStartIndex + currentSnapshotLine.length()) {
if (index() >= 0 && index() < size()) {
int currentLine = NbDocument.findLineNumber(document, index());
currentSnapshotLineStartIndex = NbDocument.findLineOffset(document, currentLine);
int endIndex = (currentLine < NbDocument.findLineRootElement(document).getElementCount() - 1) ? NbDocument.findLineOffset(document, currentLine + 1) : document.getLength();
try {
currentSnapshotLine = document.getText(currentSnapshotLineStartIndex, endIndex - currentSnapshotLineStartIndex).toString();
} catch (BadLocationException ex) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
}
} else {
currentSnapshotLine = null;
currentSnapshotLineStartIndex = 0;
}
}
}
}