我有以下语法示例:
start: (comments | removes)*
comments: COMMENT;
removes: REMOVE_ME;
COMMENT: ';'~('n'|'r')*;
REMOVE_ME: 'remove_me';
fragment NEW_LINE: (('n')
|('r')
|('rn'));
NEW_LINES: NEW_LINE+ -> channel(HIDDEN);
OTHER: . -> channel(HIDDEN);
我有以下示例文本
; comments here
; please come closer comment!
remove_me
remove_me
; comment
当我访问每个规则时,我可以使用令牌重写器来删除令牌
rewritter.delete(ctx.REMOVE_ME);
然而,我想做的是,在REMOVE_ME之前清理空的新行,最后得到如下文本。
; comments here
; please come closer comment!
; comment
我如何要求重写器删除以前的新行,直到找到另一个构造或文件的开头?
UPDATE我解决这个问题的第一次尝试是更改语法。事实上,语法倾向于忽略回车符和空格字符。
我用你的语法:
grammar Toek;
start: (comments|removes)*;
comments: COMMENT;
removes: REMOVE_ME;
COMMENT: ';'~('n'|'r')*;
REMOVE_ME: 'remove_me';
fragment NEW_LINE: (('n')
|('r')
|('rn'));
NEW_LINES: NEW_LINE+ -> channel(HIDDEN);
OTHER: . -> channel(HIDDEN);
然后我写了一个简单的JUNIT测试来解析一个字符串(你写的那个(,然后应用我的解决方案。该解决方案基于函数编程(这只是为了简化代码,没有必要(。当ANTLR完成替换您指定的规则时,我获取获得的字符串,将其拆分为行,并删除所有空行。
测试(JUNIT(和一些需要的类:
@Test
public void testOK() throws Throwable {
final String text = "; comments heren" +
"; please come closer comment!" +
"n" +
"n" +
"remove_me" +
"n"+
"n" +
"remove_me" +
"n" +
"; comment";
ParseTreeWalker walker = new ParseTreeWalker();
List<Triple<Token, Token, String>> replace = new ArrayList<>();
ToekBaseListener listener = new ToekBaseListener() {
@Override
public void enterRemoves(RemovesContext ctx) {
System.out.println("-: [" + ctx.getText() + "]");
replace.add(new Pair<Token, Token,>(ctx.start, ctx.stop));
}
};
ToekLexer lexer = new ToekLexer(CharStreams.fromString(text));
CommonTokenStream tokens = new CommonTokenStream(lexer);
ToekParser parser = new ToekParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(new JQLBaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line,
int charPositionInLine, String msg, RecognitionException e) {
System.out.println(String.format("unespected char at pos %s of text '%s'", charPositionInLine, text));
}
});
ParserRuleContext context = parser.start();
walker.walk(listener, context);
TokenStreamRewriter rewriter = new TokenStreamRewriter(tokens);
for (Triple<Token, Token, String> item : replace) {
rewriter.replace(item.value0, item.value1, "");
}
String solution=split(rewriter.getText());
System.out.println(solution);
}
...
public class Pair {
public Pair(double k ,double v) {
key=k;
value=v;
}
private String key;
private String value;
public String getKey() { return key; }
public String getValue() { return value; }
}
以及负责解决的方法。一些解释:取字符串,在流中转换(按'\n'拆分(,只过滤大小大于0的元素,然后重新组合在一起。
public static String removeBlankLines(String str) {
return Stream.of(str.split("n"))
.filter(elem -> elem!=null && elem.trim().length()>0)
.collect(Collectors.joining("n"));
}
输出如您所愿:
; comments here
; please come closer comment!
; comment