2013-04-22 145 views
4

如何使NetBeans LexerInput适应ANTLR的CharStream。我有下一个实施,但不能很好地工作。我想通过ANTLR词法分析器为NetBeans平台添加一种新语言。NetBeans平台语言和ANTLR词法分析器

Lexer只发出EOF,但令牌类型正常,我不明白。

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]' 

回答

4

我也在尝试使用ANTLR 4制作NetBeans插件。以下是我在修改从that tutorial后想出的内容。它到目前为止对我有用。

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); 
    } 
} 
+1

getText有更好的实现吗?如果输入无法识别的令牌,则使用此操作将导致NetBeans显示异常。也许像'return input.readText(0,input.readLength())。toString();'?使用提供的'Interval'参数也会导致错误,因为它有时超出了NetBeans允许的范围。 – 2013-12-31 16:23:47

-1

阿谷歌查询 “ANTLR的NetBeans”,揭示了一些文章,虽然V3的不V4。例如, http://wiki.netbeans.org/New_Language_Support_Tutorial_Antlr

您是否以某种方式运行了不同的查询?

+0

是的,我在提问之前使用了本教程。我的ANTLR令牌类型正常,但是文本是,序列号是-1。我编辑更多信息的问题。如果我运行一个普通的InputStream没有问题的词法分析器。 – 2013-04-22 17:48:00

0

我修改了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希望有助于提高它。