Parsing 使用递归下降从该语法生成表达式

Parsing 使用递归下降从该语法生成表达式,parsing,language-agnostic,graph,recursive-descent,Parsing,Language Agnostic,Graph,Recursive Descent,我有一个简单的语法。实际上,我使用的语法更复杂,但这是说明我的问题的最小子集 Expr ::= Value Suffix | "(" Expr ")" Suffix Suffix ::= "->" Expr | "<-" Expr | Expr | epsilon 也就是说,a转到b和(c->(d)(e))的结果,c转到d和e。我试图为这些表达式生成一个抽象语法树,但遇到了困难,因为所有运算符都可以接受任意数量的

我有一个简单的语法。实际上,我使用的语法更复杂,但这是说明我的问题的最小子集

Expr ::= Value Suffix
       | "(" Expr ")" Suffix

Suffix ::= "->" Expr
         | "<-" Expr
         | Expr
         | epsilon
也就是说,
a
转到
b
(c->(d)(e))
的结果,
c
转到
d
e
。我试图为这些表达式生成一个抽象语法树,但遇到了困难,因为所有运算符都可以接受任意数量的操作数。我宁愿在递归下降解析方法中保留生成AST的逻辑,因为它避免了重复提取表达式的逻辑。我目前的策略如下:

  • 如果出现
    ,将其推送到输出

  • 如果出现从或到的

  • 输出一个分隔符

  • 获取下一个
    Expr

  • 创建一个
    链接
    节点

  • 将输出中的第一组操作数弹出到
    链接中
    ,直到出现分隔符

  • 清除发现的分隔符

  • 将第二组操作数弹出到
    链接中
    ,直到出现分隔符

  • 链接
    推到输出

  • 如果我在没有遵循步骤2.3–2.7的情况下运行这个过程,我会得到一个值和分隔符的列表。对于上面引用的表达式,
    a->b(c->(d)(e))
    ,输出应为:

    A sep_1 B sep_2 C sep_3 D E
    
    应用于
    规则将产生:

    A sep_1 B sep_2 (link from C to {D, E})
    
    随后:

    (link from A to {B, (link from C to {D, E})})
    
    需要注意的重要一点是,
    sep_2
    ,这对于分隔第二个
    ->
    的左侧操作数至关重要,但没有出现,因此解析器认为表达式实际上是编写的:

    a -> (b c -> (d) (e))
    

    为了用我当前的策略解决这个问题,我需要一种在相邻表达式之间生成分隔符的方法,但前提是当前表达式是括号中包含的
    From
    to
    表达式。如果这是可能的,那么我只是没有看到它,答案应该很简单。但是,如果有更好的方法,请告诉我

    我没有尝试详细分析它,但是:“
    表达式括在括号中”听起来很像“上下文相关”,递归下降无法直接处理。为了避免上下文依赖,您可能需要为括号中的
    From
    To
    From
    To
    单独生成一个不带括号的产品

    编辑:虽然现在做任何好事都为时已晚,但如果我对您想要匹配的内容的理解是正确的,我想我会这样写:

    Graph := 
           | List Sep Graph
           ;
    
    Sep := "->"
         | "<-"
         ;
    
    List :=
          | Value List
          ;
    
    Value := Number 
          | Identifier 
          | String 
          | '(' Graph ')'
          ;
    
    Graph:=
    |列表Sep图
    ;
    九月:=“->”
    
    |“啊哈!没错。我将尝试添加另一个生成规则。通常我不使用递归下降,因为我不喜欢重构复杂的语法,所以这对我来说是一种学习经验。一切就绪!感谢您的帮助。”。
    Graph := 
           | List Sep Graph
           ;
    
    Sep := "->"
         | "<-"
         ;
    
    List :=
          | Value List
          ;
    
    Value := Number 
          | Identifier 
          | String 
          | '(' Graph ')'
          ;