2 个不稳定版本

使用旧的 Rust 2015

0.2.0 2018年12月4日
0.1.0 2018年5月31日

#2372 in 解析器实现


用于 polonius

Apache-2.0/MIT

8KB
250

Polonius 解析器

Polonius 解析器是一个小型、手动编写的解析器,用于解析来自 rustc 测试用例

// program description
placeholders { 'a, 'b, 'c }

// block description
block B0 {
    // 0:
    loan_invalidated_at(L0);

    // 1:
    loan_killed_at(L2);

    loan_invalidated_at(L1) / use('a, 'b);

    // CFG
    goto B1, B2;
}

block B1 {
    use('a), outlives('a: 'b), loan_issued_at('b, L1);
}

用法

polonius_parser 链接库提供了一个名为 parse_input 的单函数,它将程序描述作为输入字符串。输入将被成功解析为 ir::Input,或者返回一个 ParseErrorir 结构体是一个小型、公开的数据模型。

架构

polonius_parser 被实现为一个 Lexer,它是一个 Iterator,从源文本中提取 Token,以及一个 Parser,它对这些 Tokens 进行操作。解析器是一个简单的递归下降解析器,具有 1 个令牌的预览(使用 Peekable)。我们使用 T! 宏在整个实现中快速且清晰地引用令牌类型。

添加事实

为了将解析器扩展为新的 loan_bazzles_var_at 事实,执行以下更改

  • TokenKind 添加一个新的变体 KwLoanBazzlesVarAt,用于 loan_bazzles_var_at 关键字(token.rs)。
  • 将关键字的缩写添加到 T! 宏中,并将新的关键字类型添加到 TokenKindDisplay 实现。
  • 为任何引入的新语法添加额外的令牌,例如,如果关系表示为 L1 $ V1,添加 $
  • Lexer::valid_tokenlexer.rs)中添加一个情况
    kw if kw.starts_with("loan_bazzles_var_at".as_bytes()) => {
        ("loan_bazzles_var_at".len() as u32, T![loan_bazzles_var_at])
    }
    
  • 对于额外的令牌类型,根据需要添加情况。在我们的示例中,添加以下内容:
    [b'$', ..] => (1, T![$]),
    
  • ir数据模型中将Fact枚举添加一个变体来表示新的事实。对我们来说,是这样:
    LoanBazzlesVarAt { loan: String, variable: String },
    
  • Parser::parse_factparser.rs)中为新的事实添加一个情况
    T![loan_bazzles_var_at] => { /* New parsing logic here */ }
    
    如果成功,则返回Ok(Fact::LoanBazzlesVarAt { .. })。对于我们的示例
      T![loan_bazzles_var_at] => { 
          self.consume(T![loan_bazzles_var_at])?;
          self.consume(T!['('])?;
          let loan = self.parse_parameter(T![loan])?;
          self.consume(T![$])?;
          let variable = self.parse_parameter(T![variable])?;
          self.consume(T![')'])?;
          Ok(Fact::LoanBazzlesVarAt { loan, variable })
       }
    

自定义关系

当然,也可以通过遵循相同的步骤向词法分析器添加令牌、编写自己的解析方法并将它们添加到parse_input中来添加自定义关系。在这种情况下,应将相应的ir表示添加到数据模型中。

依赖关系

~2.2–4.5MB
~80K SLoC