我必须解析由两部分组成的文件。在第一个中,必须跳过新行。在第二个中,它们很重要并用作分隔符。
我想避免像http://www.antlr.org/wiki/pages/viewpage.action?pageId=1734这样的解决方案,而是使用谓词。
目前,我有类似的东西:
WS: ( ' ' | '\t' | NEWLINE) {SKIP();};
fragment NEWLINE : '\r'|'\n'|'\r\n';
我尝试添加一个动态范围的变量keepNewline
,当“输入”文件的第二部分时,该变量设置为true。
但是,我无法创建正确的谓词来关闭换行符的“跳过”。
非常感谢任何帮助。
最好的问候。
答案 0 :(得分:4)
这比你想象的要容易:你甚至不需要谓词。
假设您希望仅在<pre>
... </pre>
标记内保留换行符。以下虚拟语法就是这样:
grammar Pre;
@lexer::members {
private boolean keepNewLine = false;
}
parse
: (t=.
{
System.out.printf("\%-10s '\%s'\n", tokenNames[$t.type], $t.text.replace("\n", "\\n"));
}
)*
EOF
;
Word
: ('a'..'z' | 'A'..'Z')+
;
OPr
: '<pre>' {keepNewLine = true;}
;
CPr
: '</pre>' {keepNewLine = false;}
;
NewLine
: ('\r'? '\n' | '\r') {if(!keepNewLine) skip();}
;
Space
: (' ' | '\t') {skip();}
;
您可以使用该课程进行测试:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
PreLexer lexer = new PreLexer(new ANTLRFileStream("in.txt"));
PreParser parser = new PreParser(new CommonTokenStream(lexer));
parser.parse();
}
}
如果in.txt
包含:
foo bar
<pre>
a
b
</pre>
baz
运行Main
类的输出将是:
Word 'foo'
Word 'bar'
OPr '<pre>'
NewLine '\n'
Word 'a'
NewLine '\n'
NewLine '\n'
Word 'b'
NewLine '\n'
CPr '</pre>'
Word 'baz'