【问题标题】:Recursive Decent Parsing递归下降解析
【发布时间】:2016-02-22 04:51:43
【问题描述】:

我已经构建了一个基于语法的递归体面解析器。目前我的解析器只告诉语法是否接受输入的令牌序列。如果语法接受输入和抽象语法树,我想返回。我不知道该怎么做。

到目前为止,我所拥有的是一个对应于语法中每个生产规则的函数。我已经改变了语法,因此终端始终是每个生产规则的第一个元素。下面是我尝试为其构建语法树的语法子集。

program -> VAR = exp
exp -> NUM term
exp -> LEFTPAR exp RIGHTPAR
term -> MUL NUM term
term -> DIV NUM term
term -> . (empty)

规则的函数示例如下:

public Pair<bool, Token> exp(Token tok)
{
    if (tok.type == NUM)
    {
         return term(tok.next);
    }
    if (tok.type = LEFTPAR)
    {
         Pair<bool, Token> temp = exp(tok.next);
         if (temp.left && temp.right.type == RIGHTPAR)
             return new Pair<bool, Token>(true,temp.right.next);
         return new Pair<bool, Token>(false,null);
    }
}

将这样的函数转换为语法树构建器的策略是什么?我试图将一个树节点作为输入传递给所有函数,但是当存在具有多个非终端的规则时,它会变得更加混乱。似乎构建解析树会更容易,然后将其转换为 AST 后缀。任何帮助表示赞赏!

【问题讨论】:

  • 查看我关于如何构建递归下降解析器的回答,其中讨论了如何构建 AST。 stackoverflow.com/questions/2245962/…(您不必让每个规则都以终端开头;迭代可以处理许多“左递归”情况。)
  • 谢谢!这很有帮助!当您在我的示例中具有像 term 这样的可空规则或多个(如在我的完整语法中)时,您会怎么做?似乎唯一的解决方案是有一堆 if 语句来检查哪些是空的,然后不返回它们。
  • 由于您可以控制每个规则返回的节点,因此您可以将任何您喜欢的内容向上传递。是的,您可能需要复杂的逻辑来决定在每个规则中实际构建什么。这就是拥有与语法(例如 CST)的形状不完全相同的 AST 的代价。对于小型语法,您可能愿意进行额外的编码。对于大型或快速发展的语法,构建与语法相同形状的树是无脑且容易的。你没有得到一个“真正的”AST,但如果你按照我的建议去消除一些节点,你得到的就足够接近了。
  • 我发现递归下降解析适合通过面向过程的语言实现,但并不完全适合面向对象的编程。

标签: c# parsing abstract-syntax-tree recursive-descent


【解决方案1】:

这是一个将参数解析为函数的示例。这是在 C 中,但想法转移了,即您在解析令牌流时构建 AST。

这个函数解析像foo : double这样的字符串

static void parse_arg(parser_obj *obj, AstFunc *func) {
  Token   * tok;
  TokenId   tid = peek(obj);

  if(tid == T_PAREN_R) {
    return;
  }
  EXPECT(T_ID);
  tok = t(obj);
  char *arg_name = tok_value(tok);
  EXPECT_EAT(T_COLON);

  tok = t(obj);
  ctype arg_type = tokid_to_type(tok_id(tok));
  func->ops->new_arg(func, arg_name, arg_type);
}

func 对象实际上是 AST 中的一个节点,在这种情况下,对于多个参数,当我们添加一个新参数时,它将被添加到列表或树或您想要使用的任何数据结构中'完成解析。

在下一行中,我们将一个 arg 添加到对象 func

func->ops->new_arg(func, arg_name, arg_type);

func 的实际内部结构,即正在构建的树的形状或其实现方式对解析器不可见。

【讨论】:

    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多