微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

antlr4 语法从单个 InputStream

如何解决antlr4 语法从单个 InputStream

我有一个 InputStream 包含这样的重复块:

fld1:val1
fld2:val2

[A B C D]
[E F]

fld1:val3
fld2:val4

[M N]
[Q S T Y]

fld1:val5
...

我希望构建一个解决方案,我可以在其中解析 fld:val 块,跳过空行分隔符,然后解析“listy”部分,然后在下一个空行停止解析并将解析器重置为相同的打开流以处理下一个块。我想我可以通过访问解析器并调用 exitListy 来覆盖 baselistener 类 reset() 回调。理想情况下,这将结束 ParseTree t = parser.parse()调用链,并让控制权立即返回到 parse() 之后的代码,我对此进行了试验,并且在某种程度上可以预见,这里出现了空指针异常:org.antlr.v4.runtime.Parser.exitRule(Parser.java:639) I无法更改输入流的格式,例如插入 snip-here 标记或类似内容

解决方法

(基于评论的全新答案)

侦听器对解析完成后返回的 ParseTree 进行操作。在您的情况下,看起来您将收听基本上无休止的流,并希望定期返回数据。

我强烈推荐来自 Pragmatic Programmers 的“The Definitive ANTLR 4 Reference”。

有两个非常相关的部分:

  • “在解析过程中让事情发生”
  • “无缓冲的字符和令牌流”

对于您的语法,请尝试类似于以下“草稿”的内容(这可能不会在您想要的时候准确报告,但希望能给您提供使用的想法)

grammar Streaming;

@parser::members {
    java.util.function.Consumer<MyData> consumer;
    MyData myData = new MyData();
    public StreamingParser(TokenStream input,java.util.function.Consumer<MyData> consumer) {
        this(input);
        this.consumer = consumer;
    }
}

stream: (fldLine emptyLine listLine emptyLine) EOF;

fldLine:
    fld = ITEM COLON val = ITEM EOL {
    // add data to MyDataObject
};

listLine:
    O_BRACKET (items = ITEM)* C_BRACKET {
    // add data to MyDataObject
};

emptyLine:
    EOL {
    consumer.accept(myData);
    // reset myData
};

O_BRACKET: '[';
C_BRACKET: ']';
EOL: '\n';
COLON: ':';
ITEM: [a-zA-Z][a-zA-Z0-9]*;
SPACE: ' ' -> skip;

这利用了第一部分中描述的嵌入式操作。

然后第二部分描述如何使用无缓冲流。

类似的东西(未经测试;直接从参考书中提取)

CharStream input = new UnbufferedCharStream(<your stream>);
StreamingLexer lex = new StreamingLexer(input);
lex.setTokenFactory(new CommonTokenFactory(true));
TokenStream tokens = new UnbufferedTokenStream<CommonToken>(lex);
StreamingParser parser = new StreamingParser(tokens,// This lambda will handle data reported back when a blank line is encountered
     myData -> handle(myData));
// You just want ANTLR reporting back periodically
// not building a giant parse tree
parser.setBuildParseTree(false); 
parser.stream();  // won't return until you shut down the input stream

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。