首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >抗Serialization的序列化

抗Serialization的序列化
EN

Stack Overflow用户
提问于 2014-03-21 14:50:53
回答 2查看 2.7K关注 0票数 1

我有一个生成的语法,它做两件事:

  • 检查特定域语言的语法。
  • 根据特定领域的语言计算输入。

这两个函数是分开的,让我们将它们称为These ()和These()。

validate()函数从字符串输入构建树,同时确保它满足BNF对语言的要求。values ()函数将值插入到该树中,以获得结果(通常为true或false)。

代码当前所做的是每次在输入上运行input (),只为了生成用于计算()的树。有些输入需要60秒来检查。我想要做的是序列化validate()的结果(假设它符合语法要求),将序列化后的表单存储在后端数据库中,然后将其从数据库中加载,作为validate()的一部分。

我注意到可以在解析树上执行方法toStringTree(),并检索LISP样式树。但是,我能否将LISP样式树还原为ANTLR解析树?如果没有,是否有人推荐另一种方法来序列化和存储生成的解析树?

谢谢你的帮助。

杰森

EN

回答 2

Stack Overflow用户

发布于 2014-03-21 14:58:43

ANTLR 4的ParseRuleContext数据结构(生成的解析器用于表示解析树中语法规则的ParseTree的具体实现)在默认情况下是不可序列化的。打开第233期上的项目问题跟踪器涵盖功能请求。但是,根据我使用ANTLR进行解析的许多应用程序的经验,从长远来看,我不相信序列化解析树是有用的。对于序列化解析树的每个问题,一个更好的解决方案已经存在。

另一个选项是将最后一个已知的有效文件的散列存储在数据库中。在使用解析器创建解析树之后,如果输入文件具有与上次验证相同的散列,则可以跳过验证步骤。这利用了反two 4的两个方面:

  1. 对于同一个输入文件,运行两次解析器将产生相同的解析树。
  2. ANTLR 4解析器在几乎所有情况下都非常快(例如,Java语法每秒可以处理大约20 in的源)。剩下的情况往往是由于ANTLRWorks 2.2中新的解析器解释器特性可以分析并提出改进建议的语法规则。

如果您需要的性能超出了所获得的性能,那么解析树并不是您应该使用的数据结构。StringTemplate 4比StringTemplate 3具有巨大的性能优势,主要是因为解释器从使用AST(相当于此推理的解析树)转换为线性字节码表示/解释器。由于性能原因,ST4的AST永远不需要序列化,因为字节码将被序列化。实际上,C#端口StringTemplate 4正是提供了这个特性。

票数 1
EN

Stack Overflow用户

发布于 2014-04-10 16:43:20

如果语法的输入数据是由几个独立的块组成的,您可以尝试分别存储每个块的字符串,并使用ThreadPool为每个块独立运行解析过程。

例如,假设输入数据是一组方法声明:

代码语言:javascript
复制
int add(int a, int b) {
   return a+b;
}

int mul(int a, int b) {
    return a*b;
}

...

语法是这样的:

代码语言:javascript
复制
methodList : methodDeclaration methodList
           |
           ;
methodDeclaration : // your method declaration rules...

解析器的第一次运行只是收集每个方法文本并存储它。解析器以methodList规则启动进程。

代码语言:javascript
复制
void visitMethodList(MethodListContext ctx) {
    if(ctx.methodDeclaration() != null) {
        String methodStr = formatParseTree(ctx.methodDeclaration(), " ");
        // store methodStr for later parsing
    }

    // visit next method list item, if any
    if(ctx.methodList() != null) {
        visit(ctx.methodList());
    }
}

第二次运行启动每个方法声明的解析(例如,在一个单独的线程中)。为此,解析器从methodDeclaration规则开始。

代码语言:javascript
复制
void visitMethodDeclaration(MethodDeclarationContext ctx) {
    // parse the method block
}

如果直接调用methodDeclaration规则的ctx.methodDeclaration().getText()将合并所有子节点AntLR文档的文本,则会对其进行格式化,这可能使其无法再次进行解析。如果空白是语法中的标记分隔符,那么在标记之间添加一个空格不应该更改解析树。

代码语言:javascript
复制
String formatParseTree(ParseTree tree, String separator) {
    StringBuilder builder = new StringBuilder();
    for(int i = 0; i < tree.getChildCount(); i ++) {
        ParseTree child = tree.getChild(i);

        if(child instanceof TerminalNode) {
            builder.append(child.getText());
            builder.append(separator);
        } else if(child instanceof RuleContext) {
            builder.append(formatParseTree(child, separator));
        }
    }

    return builder.toString();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22562061

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档