• 编译器设计-解析类型


    编译器设计-解析类型

    Compiler Design - Types of Parsing

    语法分析器遵循由上下文无关语法定义的产生式规则。生成规则的实现方式(派生)将解析分为两种类型:自上而下解析和自下而上解析。

    自顶向下分析Top-down Parsing             

    当解析器开始从开始符号构造解析树,然后尝试将开始符号转换为输入时,称为自顶向下解析。             

    递归下降解析:它是自顶向下解析的一种常见形式。它被称为递归,因为它使用递归过程来处理输入。递归下降解析受到回溯的影响。             

    回溯:这意味着,如果产品的一个派生失败,语法分析器将使用同一产品的不同规则重新启动进程。这种技术可以多次处理输入字符串以确定正确的生产。             

    自下而上分析Bottom-up Parsing             

    顾名思义,自底向上的解析从输入符号开始,并尝试构建解析树直至开始符号。

    Example:

    Input string : a + b * c

    Production rules:

    S → E

    E → E + T

    E → E * T

    E → T

    T → id

    Let us start bottom-up parsing

    a + b * c

    读取输入并检查是否有任何生产与输入匹配:

    a + b * c
    T + b * c
    E + b * c
    E + T * c
    E * c
    E * T
    E
    S

    在上一章中,我们了解到自顶向下解析技术解析输入,并开始从根节点逐渐向下移动到叶节点构建解析树。

    递归下降分析Recursive Descent Parsing             

    递归下降是一种自顶向下的解析技术,它从顶部构造解析树,从左到右读取输入。它对每个终端和非终端实体使用过程。这种解析技术递归地解析输入以生成解析树,这可能需要也可能不需要回溯。但与之相关联的语法(如果没有保留因子)不能避免回溯。一种不需要任何回溯的递归下降解析称为预测解析。             

    这种解析技术被认为是递归的,因为它使用的上下文无关语法本质上是递归的。             

    回溯Back-tracking             

    自上而下的解析器从根节点(开始符号)开始,并根据生产规则匹配输入字符串以替换它们(如果匹配)。要理解这一点,请以CFG为例:

    S  rXd | rZd
    X  oa | ea
    Z  ai

    对于输入字符串:read,自上而下的解析器,其行为如下:             

    它将从生产规则中的S开始,并将其收益率与输入的最左边的字母(即“r”)匹配。S(S→rXd)的产生与之相匹配。所以自上而下的解析器前进到下一个输入字母(即“e”)。解析器尝试展开非终端“X”,并从左侧检查其结果(X→oa)。它与下一个输入符号不匹配。所以自上而下的解析器回溯以获得X的下一个产生式规则(X→ea)。             

    现在解析器按顺序匹配所有输入字母。接受字符串。

    预测分析器 Predictive parser            

    Predictive parser是一种递归下降解析器,它能够预测将使用哪个产品来替换输入字符串。预测解析器不受回溯的影响。             

    为了完成它的任务,预测解析器使用一个前瞻指针,它指向下一个输入符号。为了使解析器无需回溯,预测解析器对语法施加一些约束,只接受一类称为LL(k)语法的语法。

    预测性分析使用堆栈和分析表来分析输入并生成分析树。堆栈和输入都包含一个结束符号$,表示堆栈为空并且输入被消耗。解析器引用解析表来决定输入和堆栈元素的组合。

    在递归下降解析中,对于单个输入实例,解析器可能有多个产品可供选择,而在预测解析器中,每个步骤最多有一个产品可供选择。可能存在没有与输入字符串匹配的产品的实例,从而导致分析过程失败。             

    LL分析器LL Parser             

    LL语法分析器接受LL语法。LL文法是上下文无关文法的一个子集,但有一定的限制,要得到简化的版本,才能实现容易。LL语法可以通过递归下降和表驱动两种算法来实现。             

    LL解析器表示为LL(k)。第一个L in LL(k)从左到右解析输入,第二个L in LL(k)表示最左边的派生,k本身表示look ahead的数量。一般k=1,所以LL(k)也可以写成LL(1)。

    LL解析算法 LL Parser Algorithm            

    对于解析器的解释,我们可以使用确定性的LL(1),因为表的大小随着k的值呈指数增长。其次,如果给定的语法不是LL(1),那么对于任何给定的k,通常都不是LL(k)。              

    下面给出了LL(1)解析的算法:

    Input:
       string ω
       parsing table M for grammar G
     
    Output:
       If ω is in L(G) then left-most derivation of ω,
       error otherwise.
     
    Initial State : $S on stack (with S being start symbol)
       ω$ in the input buffer
     
    SET ip to point the first symbol of ω$.
     
    repeat
       let X be the top stack symbol and a the symbol pointed by ip.
     
       if X∈ Vt or $
          if X = a
             POP X and advance ip.
          else
             error()
          endif
          
       else       /* X is non-terminal */
          if M[X,a] = X  Y1, Y2,... Yk    
             POP X
             PUSH Yk, Yk-1,... Y1 /* Y1 on top */
             Output the production X  Y1, Y2,... Yk
          else
             error()
          endif
       endif
    until X =/* empty stack */

    如果A→α|β是G的两个不同乘积,则语法G是LL(1):             

    对于无终端,α和β都导出以a开头的字符串。             

    α和β中至多有一个可以导出空字符串。             

    如果β→t,则α不导出以跟随(a)中的终端开始的任何字符串。

  • 相关阅读:
    iBatisnet 1.5版本的配置文件的几个变化
    使用Trace时要注意
    无刷新转页面?
    无刷新“页面跳转”问题一:与AtlasToolKit协同工作
    Assembly的Release与Debug
    iBatis.Net系列(四) iBatisNet API基础
    Atlas 调用web service
    无刷新“页面跳转”
    iBatis.Net系列(六) ResultMap
    在GridView中格式化时间字段
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/13183676.html
Copyright © 2020-2023  润新知