正如我在Antlr greedy-option中所描述的,我在使用一种可能在字符串文字中包含字符串文字的语言时遇到了一些问题,例如:
开始:“img src="test.jpg""
Bart Kiers 先生在我的帖子中提到,不可能创建一个可以解决我的问题的语法。因此我决定将语言更改为:
开始:“img src='test.jpg'”
在启动词法分析器(和解析器)之前。
文件输入可以是:
开始:“aaa”aaa“ “啊啊啊啊啊” :END_START 开始:“aaa”aaa“ “啊”啊 一个 啊” :END_START 开始:“aaab”bbaaaa“ :END_START
所以我有一个解决方案,但它是不正确的。我有两个关于我的问题的问题(在代码下方)。我的代码是:
public static void main(String[] args) {
try{
FileInputStream fis = new FileInputStream("src/file.txt");
String preparedCode = preparingCode(fis);
ANTLRStringStream in = new ANTLRStringStream(preparedCode);
TestLexer lex = new TestLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lex);
TestParser parser = new TestParser(tokens);
parser.rule();
}catch(IOException ex){
ex.printStackTrace();
} catch (RecognitionException e) {
System.out.println(e.getMessage());
System.exit(0);
}
}
static String preparingCode(FileInputStream input){
DataInputStream data = new DataInputStream(input);
StringBuilder oldCode = new StringBuilder();
StringBuffer newCode = new StringBuffer(oldCode.length());
Pattern pattern = Pattern.compile("(START:\\s\")(.+)(\"\\n:END_START)");
String strLine;
try{
while ((strLine = data.readLine()) != null)
oldCode.append(strLine + "\n");
}
catch(IOException ex){
ex.printStackTrace();
}
Matcher matcher = pattern.matcher(oldCode);
while (matcher.find()) {
//eliminate quotes inside a string literal
String stringLiteral = matcher.group(2).replaceAll("\"", "'");
String replace = matcher.group(1) + stringLiteral + matcher.group(3);
matcher.appendReplacement(newCode, Matcher.quoteReplacement(replace));
}
matcher.appendTail(newCode);
System.out.println(newCode);
return newCode.toString();
}
我的问题是:
哪种模式是正确的?重要的是,字符串文字可以在多行上定义,例如 "aaaa"\n"bbb",但总是以 "\n:END_START" 行结束。我希望得到以下结果:
开始:“啊啊啊啊” “啊啊啊啊” :END_START 开始:“啊啊啊啊” 啊啊啊 一个 啊” :END_START 开始:“aaab'bbaaaa” :END_START
我玩弄了模式标志 Pattern.DOTALL
Pattern pattern = Pattern.compile("(START:\s\")(.+)(\"\n:END_START)", Pattern.DOTALL);
但这不是解决方案,因为在这种情况下它匹配一切......
-如果我会使用正确的模式,有没有其他有效的方法来解决它?
修复第一个问题
,我必须使用带有模式标志 Pattern.DOTALL 的非贪婪方法:
Pattern pattern = Pattern.compile("(START:\\s\")(.+?)(\"\\n:END_START)", Pattern.DOTALL);