我有以下Antlr4语法。
grammar Paradox;
paradox:
kvPair+;
kvPair
: atom '=' atom
| atom '=' scope
| scope
;
scope
: '{' (paradox|atom+)? '}'
;
atom
: STRING
| NUMBER
| ID (':' ID)?
;
STRING
: '"' (~'"')*? '"' ;
ID : [0-9a-zA-Z_]+ ;
NUMBER
: '-'?[0-9]+ ('.' [0-9]+)?
;
WS : [ \t\r\n]+ -> skip ;
文件为20 MB,看起来像这样
version="Boulle v1.9.1"
version_control_revision=31493
name="泰布理同胞体"
date="2269.02.09"
planet= { ... }
...
country = {
0 = {
...
name="USA"
...
food_surplus=3.598
...
}
1 = {
...
name="ENG"
...
food_surplus=2.001
...
}
...
}
...
...
表示我省略了行。实际文件在那里具有有效的语法。
说,我只需要知道国家/地区的数目,并为每个国家/地区记录名称和food_surplus。
当前我要做的是
ICharStream cstream = CharStreams.fromstring(input);
ITokenSource lexer = new ParadoxLexer(cstream);
ITokenStream tokens = new CommonTokenStream(lexer);
var parser = new ParadoxParser(tokens);
// find kvPair with key "country".
// Then .ChildCount is the number of country,
// find kvPair with key "name" to get the name of the country.
此方法有效,但缺点是运行时会消耗多达1GB的内存。请注意,我没有使用,也不知道如何使用访客模式或听众模式。
我了解大的内存消耗是由于...,我省略的行可能是数百万行。 Antlr正在为这些无关紧要的事物构建解析树。
如何减少内存消耗?
答案 0 :(得分:2)
解析器不是用于此类处理的正确工具,因为它应该验证它获得的所有输入。这本身就是解析器的主要/主要目标。如果您只对输入的一部分感兴趣,则可以先通过其他方式将其分割(例如,搜索某些定界符),然后仅将感兴趣的部分提供给解析器。
根据请求:用于侦听器/访问者的ANTLR4文档have a short description,与解析器运行生成的解析树一起使用。为了在解析过程中使用侦听器,您只需要register your listener(与解析后使用的监听器完全一样):
JavaLexer lexer = new JavaLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
JavaParser parser = new JavaParser(tokens);
MyListener extractor = new MyListener(parser);
parser.addParseListener(extractor);
JavaParser.CompilationUnitContext tree = parser.compilationUnit(); // parse a compilationUnit