注意,我知道很少的C,并且对ANTLR的C运行时没有经验,但是我的例子中的Java代码不应该太难重写成C。
你可以通过覆盖
emit(Token)
从基开始的方法
Lexer
上课并跟踪最后一个
Token
您的lexer进程:
private Token last;
@Override
public void emit(Token token) {
last = token;
super.emit(token);
}
要将其包含在lexer中,请将其添加到语法中,并介于以下两个值之间:
@lexer::members {
// your code here
}
现在你必须把
Other
规则
之前
你的
ExtraData
规则并提出
gated semantic predicate
在你之前
其他
规则检查
last
令牌是
超文本
令牌:
Other
: {behind(ExtraData)}?=> ~'-' (~' ')*
;
何处
behind(int)
方法是您的
@lexer::members { ... }
章节:
protected boolean behind(int tokenType) {
return last != null && last.getType() == tokenType;
}
这将导致
其他
要匹配的令牌
只有
如果最后一个标记是
超文本
.
一个小小的语法演示:
grammar LookBehind;
@lexer::members {
private Token last;
@Override
public void emit(Token token) {
last = token;
super.emit(token);
}
protected boolean behind(int tokenType) {
return last != null && last.getType() == tokenType;
}
}
parse
: token+ EOF
;
token
: Argument {System.out.println("Argument :: "+$Argument.text);}
| Other {System.out.println("Other :: "+$Other.text);}
| ExtraData {System.out.println("ExtraData :: "+$ExtraData.text);}
;
Argument
: '-'+ (~('-' | '#' | ' '))+
;
Other
: {behind(ExtraData)}?=> ~('-' | ' ') (~' ')*
;
ExtraData
: '#' (~'#')* '#'
;
Space
: (' ' | '\t' | '\r' | '\n') {skip();}
;
以及一个测试它的主要类:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = "-argument -argument#with hashed data# #plainhashedData#";
ANTLRStringStream in = new ANTLRStringStream(source);
LookBehindLexer lexer = new LookBehindLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LookBehindParser parser = new LookBehindParser(tokens);
parser.parse();
}
}
首先从语法生成一个解析器和lexer:
java -cp antlr-3.2.jar org.antlr.Tool LookBehind.g
然后编译全部
.java
文件夹:
javac -cp antlr-3.2.jar *.java
最后运行主类:
java -cp .:antlr-3.2.jar Main
(在Windows DO上:
java -cp .;antlr-3.2.jar Main
)
然后将产生以下输出:
Argument :: -argument
Argument :: -argument
ExtraData :: #with hashed data#
Other :: #plainhashedData#
编辑
正如你(比利)在评论中提到的,在C语言中,你不能重写方法。您还可以在
@after{ ... }
跟踪最后一个令牌何时为
超文本
并在谓词中使用该标志:
grammar LookBehind;
@lexer::members {
private boolean lastExtraData = false;
}
parse
: token+ EOF
;
token
: Argument {System.out.println("Argument :: "+$Argument.text);}
| Other {System.out.println("Other :: "+$Other.text);}
| ExtraData {System.out.println("ExtraData :: "+$ExtraData.text);}
;
Argument
@after{lastExtraData = false;}
: '-'+ (~('-' | '#' | ' '))+
;
Other
@after{lastExtraData = false;}
: {lastExtraData}?=> ~('-' | ' ') (~' ')*
;
ExtraData
@after{lastExtraData = true;}
: '#' (~'#')* '#'
;
Space
: (' ' | '\t' | '\r' | '\n') {skip();}
;
虽然这有点像黑客:在每一个lexer规则中,你都必须设置标志。
您也可以向
ANTLR mailing-list
:除了许多Antlr专家之外,维护Antlr的C运行时的人也经常出现在那里。
祝你好运!