如何使NetBeans LexerInput适应于ANTLR的CharStream。我有下一个实现,但工作不太好。我想通过ANTLR词法分析器向NetBeans平台添加一种新语言。
Lexer只发出EOF,但令牌类型是ok的,我不明白。
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.misc.Interval;
import org.netbeans.spi.lexer.LexerInput;
/**
* @author jonny
*/
public class AntlrCharStream implements CharStream {
private class CharStreamState {
int index;
int line;
int charPositionInLine;
}
private int line = 1;
private int charPositionInLine = 0;
private LexerInput input;
private String name;
private int index = 0;
private List<CharStreamState> markers;
private int markDepth = 0;
private int lastMarker;
public AntlrCharStream(LexerInput input, String name) {
this.input = input;
this.name = name;
}
@Override
public String getText(Interval intrvl) {
return input.readText().toString();
}
public String substring(int start, int stop) {
throw new UnsupportedOperationException("Not supported yet.");
}
public int LT(int i) {
return LA(i);
}
public int getLine() {
return line;
}
public void setLine(int line) {
this.line = line;
}
public void setCharPositionInLine(int pos) {
this.charPositionInLine = pos;
}
public int getCharPositionInLine() {
return charPositionInLine;
}
public void consume() {
int c = input.read();
index++;
charPositionInLine++;
if (c == 'n') {
line++;
charPositionInLine = 0;
}
}
public int LA(int i) {
if (i == 0) {
return 0; // undefined
}
int c = 0;
for (int j = 0; j < i; j++) {
c = read();
}
backup(i);
return c;
}
public int mark() {
if (markers == null) {
markers = new ArrayList<CharStreamState>();
markers.add(null); // depth 0 means no backtracking, leave blank
}
markDepth++;
CharStreamState state = null;
if (markDepth >= markers.size()) {
state = new CharStreamState();
markers.add(state);
} else {
state = (CharStreamState) markers.get(markDepth);
}
state.index = index;
state.line = line;
state.charPositionInLine = charPositionInLine;
lastMarker = markDepth;
return markDepth;
}
public void rewind() {
rewind(lastMarker);
}
public void rewind(int marker) {
CharStreamState state = (CharStreamState) markers.get(marker);
// restore stream state
seek(state.index);
line = state.line;
charPositionInLine = state.charPositionInLine;
release(marker);
}
public void release(int marker) {
// unwind any other markers made after m and release m
markDepth = marker;
// release this marker
markDepth--;
}
public void seek(int index) {
if (index < this.index) {
backup(this.index - index);
this.index = index; // just jump; don't update stream state (line, ...)
return;
}
// seek forward, consume until p hits index
while (this.index < index) {
consume();
}
}
public int index() {
return index;
}
public int size() {
return -1; //unknown...
}
public String getSourceName() {
return name;
}
private int read() {
int result = input.read();
if (result == LexerInput.EOF) {
result = CharStream.EOF;
}
return result;
}
private void backup(int count) {
input.backup(count);
}
}
'[@-1,6:6='<EOF>',<1>,2:2]'
'[@-1,7:7='<EOF>',<1>,2:3]'
'[@-1,8:15='<EOF>',<9>,2:4]'
'[@-1,16:16='<EOF>',<1>,2:12]'
'[@-1,17:23='<EOF>',<8>,2:13]'
'[@-1,24:24='<EOF>',<1>,2:20]'
'[@-1,25:25='<EOF>',<2>,2:21]'
'[@-1,26:26='<EOF>',<1>,3:0]'
'[@-1,27:27='<EOF>',<1>,3:1]'
'[@-1,28:28='<EOF>',<1>,3:2]'
'[@-1,29:29='<EOF>',<1>,3:3]'
'[@-1,30:37='<EOF>',<4>,3:4]'
'[@-1,38:38='<EOF>',<1>,3:12]'
'[@-1,39:43='<EOF>',<5>,3:13]'
'[@-1,44:44='<EOF>',<1>,3:18]'
'[@-1,45:48='<EOF>',<9>,3:19]'
'[@-1,49:49='<EOF>',<1>,3:23]'
'[@-1,50:53='<EOF>',<7>,3:24]'
'[@-1,54:54='<EOF>',<1>,3:28]'
'[@-1,55:56='<EOF>',<6>,3:29]'
'[@-1,57:57='<EOF>',<2>,3:31]'
'[@-1,58:57='<EOF>',<-1>,4:32]'
我也在尝试使用ANTLR 4制作NetBeans插件。这是我在修改了该教程中的AntlrCharStream
后得出的结论。到目前为止,这对我来说是有效的。
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.misc.Interval;
import org.netbeans.spi.lexer.LexerInput;
public class AntlrCharStream implements CharStream {
private final LexerInput input;
private final String name;
private int index = 0;
private int markDepth = 0;
public AntlrCharStream(LexerInput input, String name) {
this.input = input;
this.name = name;
}
@Override
public String getText(Interval interval) {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public void consume() {
int character = read();
if (character == EOF) {
backup(1);
throw new IllegalStateException("Attempting to consume EOF");
}
index++;
}
@Override
public int LA(int lookaheadAmount) {
if (lookaheadAmount < 0) {
return lookBack(-lookaheadAmount);
} else if (lookaheadAmount > 0) {
return lookAhead(lookaheadAmount);
} else {
return 0; //Behaviour is undefined when lookaheadAmount == 0
}
}
private int lookBack(int amount) {
backup(amount);
int character = read();
for (int i = 1; i < amount; i++) {
read();
}
return character;
}
private int lookAhead(int amount) {
int character = 0;
for (int i = 0; i < amount; i++) {
character = read();
}
backup(amount);
return character;
}
@Override
public int mark() {
return ++markDepth;
}
@Override
public void release(int marker) {
// unwind any other markers made after m and release m
markDepth = marker;
// release this marker
markDepth--;
}
@Override
public void seek(int index) {
if (index < 0) {
throw new IllegalArgumentException(String.format("Invalid index (%s < 0)", index));
}
if (index < this.index) {
backup(this.index - index);
this.index = index;
return;
}
// seek forward, consume until p hits index
while (this.index < index) {
consume();
}
}
@Override
public int index() {
return index;
}
@Override
public int size() {
throw new UnsupportedOperationException("Stream size unknown");
}
@Override
public String getSourceName() {
return name;
}
private int read() {
int result = input.read();
if (result == LexerInput.EOF) {
return EOF;
} else {
return result;
}
}
private void backup(int count) {
input.backup(count);
}
}
我已经修改了Daniel提出的实现来实现getText函数。我还修改了索引位置的跟踪方式。到目前为止,它对我来说是有效的,但因为我没有时间了,它仍然需要适当的测试。
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.misc.Interval;
import org.netbeans.spi.lexer.LexerInput;
public class AntlrCharStream implements CharStream {
private final LexerInput input;
private final String name;
private int index = 0;
private int markDepth = 0;
public AntlrCharStream(LexerInput input, String name) {
this.input = input;
this.name = name;
}
@Override
public String getText(Interval interval) {
int start = interval.a;
int stop = interval.b;
if (start < 0 || stop < start) {
return "";
}
final int pos = this.index;
final int length = interval.length();
final char[] data = new char[length];
seek(interval.a);
int r = 0;
while (r < length) {
final int character = read();
if (character == EOF) {
break;
}
data[r] = (char) character;
r++;
}
seek(pos);
if (r > 0) {
return new String(data, 0, r);
} else {
return "";
}
}
@Override
public void consume() {
int character = read();
if (character == EOF) {
backup(1);
throw new IllegalStateException("Attempting to consume EOF");
}
}
@Override
public int LA(int lookaheadAmount) {
if (lookaheadAmount < 0) {
return lookBack(-lookaheadAmount);
} else if (lookaheadAmount > 0) {
return lookAhead(lookaheadAmount);
} else {
return 0; //Behaviour is undefined when lookaheadAmount == 0
}
}
private int lookBack(int amount) {
backup(amount);
int character = read();
for (int i = 1; i < amount; i++) {
read();
}
return character;
}
private int lookAhead(int amount) {
int character = 0;
for (int i = 0; i < amount; i++) {
character = read();
}
backup(amount);
return character;
}
@Override
public int mark() {
return ++markDepth;
}
@Override
public void release(int marker) {
// unwind any other markers made after m and release m
markDepth = marker;
// release this marker
markDepth--;
}
@Override
public void seek(int index) {
if (index < 0) {
throw new IllegalArgumentException(String.format("Invalid index (%s < 0)", index));
}
if (index < this.index) {
backup(this.index - index);
return;
}
// seek forward, consume until p hits index
while (this.index < index) {
consume();
}
}
@Override
public int index() {
return index;
}
@Override
public int size() {
return -1; //unknown...
}
@Override
public String getSourceName() {
return name;
}
private int read() {
int result = input.read();
index++;
if (result == LexerInput.EOF) {
return EOF;
} else {
return result;
}
}
private void backup(int count) {
input.backup(count);
index -= count;
}
}
我在:https://gist.github.com/megothss/849fb466a21793956033中创建了一个要点,以防有人想要贡献改进它。
google查询"antlr netbeans"显示了许多文章,尽管是v3而不是v4。例如,http://wiki.netbeans.org/New_Language_Support_Tutorial_Antlr
你是否运行了不同的查询?