• Proj THUDBFuzz Paper Reading: Adaptive LL(*) Parsing: The Power of Dynamic Analysis


    Abstract

    背景:目前的语法分析技术会遇到以下困难1. 难以嵌入带有副作用的actions 2. 速度慢 3. 有二义性 4. 匹配策略违反直觉
    本文:介绍ALL(*)分析技术,对应ANTLR v4
    特点:

    1. 简单,高效,有常规topdown LL(k)parsers的预测能力,也有GLR类型文法的决策能力
    2. 虽然理论上是O(n4)的,但是实践时常是线性复杂度
    3. 在解析的时候就做语法分析
      适应范围:所有CFG
    • 对带左递归的文法,需要改写
    • 对不带左递归的文法,可以密切分析
      效果:
      比GLL和GLR有量级提升

    Intro

    LL(*)缺点:1. 无法静态确定语法条件 2. 有时无法找到能区分语法规则选项肢的DFA

    1.1 Dynamic grammar analysis

    P1:
    ALLstar用类似GLR的机制来解析。具体来说,LL解析在每个决策点,也就是说,在每个非终端符号上,都会暂停,等到决定出具体走哪条production之后才会接着拓展。
    关键点:将语法分析转移到解析阶段,不做静态语法分析
    静态分析需要考虑全部可能的序列,但是动态分析只需要考虑见到的那部分有限输入语句集合即可

    P2:
    ALLstar的主要思路是在每个决策点(每个非终端符号上)为每个选择肢都建立一个subparser,这些subparser以伪并行的方式执行直到只有一个subparser还能接着匹配。如果有多个subparser都能匹配,那么ANTLR4会先报告二义性,再选择优先级最高的production进行拓展。
    程序员也可以使用semantic predicates来避免一部分二义性问题

    P3:
    ALLstar解析器会记住分析结果,动态维护一个DFA的缓存,这样可以加速决策过程。
    不在缓存里的陌生输入会激发语法分析机制,在预测选择哪个选择肢的同时,还会用来更新DFA缓存。
    DFA很适合用来存储预测结果(Q: despite the fact that the lookahead language at a given decision typically forms a CFG)。

    P4:
    为了尽量避免nondeterminstic带来的指数级潜在复杂度,本文使用图结构的栈(graph-structured stack, GSS)来做预测,
    和GLR的差别:
    ALLstar和GLR的策略几乎一致,但是GLR会直接做解析,ALLstar只是预测该走哪条production就截止。
    ALLstar不一定会把终端符放进GSS,但是GLR一定会放

    P5:
    ALLstar的时间复杂度是O(n4),因为检查单个符号最多可以到达O(n2)的时间复杂度,不过,在时间上时间复杂度可以仅为O(n2)

    P6:
    ALLstar将语法分析移到解析阶段来做的策略导致了语法功能测试(grammar functional testing)的额外负担。
    grammar functional testing中,程序员通常试图尽量覆盖尽可能多的grammar position和输入序列组合,以此找到二义性和未处理的情况

    P7:
    介绍ANTLR4

    P8:
    文章结构

    2 ANTLR4

    1. 接受不包含间接左递归(A->B, B->A)和隐藏左递归(A->BA, B->episilon)的其他全部CFG作为输入。
    2. 能够生成多种语言的parser,包括java和C#
    3. 使用类似yacc语法,支持EBNF的operators
    4. ANTLR4 grammars can be scannerless and composable because ALLstar languages are closed under union,便于模块化
    5. 程序员能够嵌套具有副作用的actions(mutators)。当然,在推测阶段,这些mutators不会被激发。
    6. 支持semantic predicates,即无副作用的返回布尔值的表达式,用来确定某个production是否可行
    • 能用来检测parse stack和input context

    2.1 sample grammar

    ANTLR3和ANTLR4区别

    1. 允许rule expr左递归
    2. 对于state: expr '=' 和state: expr ';'两个分支,ANTLR3会检测到recursion,然后启动backtracking
    3. ANTLR4加入了semantic predicates

    2.2 Left-recursion removal

    采用语法重写技术。
    出于工程考虑,不支持间接左递归和隐藏左递归

    2.3 Lexical analysis with ALLstar

    ANTLR中分词是直接用了GLR类似的方法,动态分析并且直接开始解析,而不是只用动态分析来决定走哪个production
    Q: (没有搞清楚因果关系) The key difference is that ALLstar lexers are predicated context-free grammars not just regular expressions so they can recognize context-free tokens such as nested comments and can gate tokens in and out according to semantic context

    ANTLR也很适合Scannerless Parsing,用于处理上下文敏感的分词问题,比如混合C和SQL语法

    3. Intro to ALLstar Parsing

    P1:
    ALLstar和LLk以及LLstar文法不同,会尽量选择第一个可以解析的production。

    P2:
    解析器会动态增量为每个非终端符号都创建一个lookahead DFA,来预测当前输入应当匹配哪一条production。实验证明大多数解析都能够利用到这个cache DFA

    P3:

    ALLstar和传统的topdown LL文法解析的过程基本一致,只是多了一个函数调用 adaptivePredict,用于构筑lookahead DFA,而不是仅仅把lookahead tokens和候选tokens做静态对照
    adaptivePredict输入参数: 1. 当前非终端符 2. parser call stack 返回: 可用的production编号,如果没有可用production,会抛出异常

    P4:
    与NFA-DFA subset construction进行类比
    ALLstar DFA state是匹配完毕到达这个状态的输入之后的parser configurations

    这里,ALLstar用augmented recursive transition network(ATN)来模拟语法结构

    P5:
    ATN configuration代表子解析器的执行状态,用来追踪ATN的状态。
    ATN configuration=(p, i, γ),这里p是ATN state, i是预测中production编号,γ是ATN subparser call stack。
    与静态LLstar分析不同,ALLstar只用已经出现的lookahead sequence来建立DFA

    P6-P7:
    AdaptivePredict步骤

    1. 创建初始状态D0
    2. (以Fig3为例) 添加ATN configuration (p, 1, []), (q, 2, []),分别对应编号为1和2的两个选项肢
    3. 为每个匹配了lookahead symbol之后能够到达的状态建个新状态,再建对应的边
    4. 消耗ATN configuration,直到走到(-,i,-)为止(或者只有一个production可用)
      这里,如果是已经走过的路,就直接用而无需模拟,如果是没有走过的,就启用ATN模拟并且记录
      Q: 这里是否记录没有接受当前input sequence但是ATN模拟走过的路?
    • 猜测: 不会接受
      Q: Targeting existing states is how cycles can appear in the DFA

    3.1 Predictions sensitive to the call stack

    P1:
    为了支持几乎所有CFG文法,ALLstar必须要考虑stack-sensitive prediction
    例如,java method就需要根据自己是否在interface或者method中决定不同的行为。
    例2:
    S → xB | yC, B → Aa, C → Aba, A → b | epsilon
    这里对于lookahead序列ba来说,到底是走A->b还是A->epsilon与S->xB还是x->yC有关

    P2:
    无需parser call stack的解析器被称为Strong LL parsers。LL常常被默认地限制为SLL文法。

    P3:
    为每种callstack都建立一个DFA不现实,ANTLR利用大部分解析都对应SLL文法production的特点,无视callstack来建立DFA。
    如果找到了prediction conflict,为了进一步确认DFA找到的到底是二义性还是无视parser call stack导致的,adaptivePredict会重新检查一遍lookahead,这个时候会考虑parser stack,本文称为Two-stage ALLstar parsing,能加速解析8倍。

    3.2 Two-stage ALLstar parsing

    先用SLLmode进行parse,然后再试LL mode

    4 Predicated grammars, ATNs and DFA





    5 ALLstar parsing algo

    5.1 Graph-structured call stacks

    对于两个在state p的子解析器来说,qγ1和qγ2的行动在q出栈之前都是一致的,所以可以利用这个性质,将configuration(p, i, γ1)和(p, i, γ2)合并为新的(p,i,Tao)

    5.2 ALLstar parsing functions





    5.3 Conflict and ambiguity detection



    6 Theoretical results

    Theorem 6.1. (Correctness). The ALLstar parser for non-leftrecursive G recognizes sentence w iff w ∈ L(G).
    Theorem 6.2. ALLstar languages are closed under union.
    Theorem 6.3. ALLstar parsing of n symbols has O(n4) time.
    Theorem 6.4. A GSS has O(n) nodes for n input symbols.
    Theorem 6.5. Two-stage parsing for non-left-recursive G recognizes sentence w iff w ∈ L(G).

    7 Empirical results

    7.1 Comparing ALL star's speed to other parsers

    竞品:
    hand-tuned recursive-descent with precedence parsing, LL(k), LL(*), PEG, LALR(1), ALL(*), GLR, and GLL

    实验数据: 12920 Java6源文件

    7.2 ALLstar performance across languages

    实验数据: 8种语言,C,Java, Verilog2001, JSON, DOT, Lua, XML, Erlang

    7.3 Effect of lookahead DFA on performance

    7.4 Empirical parse-time complexity

  • 相关阅读:
    机器学习(3)- 学习建议<误差出现如何解决?>
    机器学习(2)- 神经网络
    推荐系统(2)
    机器学习(1)- 概述&线性回归&逻辑回归&正则化
    朴素贝叶斯法(naive Bayes)
    约瑟夫环(java)
    AJAX请求详解 同步异步 GET和POST
    AJAX
    JspWriter与PrintWriter(转)
    Jsunit
  • 原文地址:https://www.cnblogs.com/xuesu/p/14701702.html
Copyright © 2020-2023  润新知