Skip to content

Unconnectable/rust-practice

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

1.表达式计算expr-eval

词法分析 (Tokenizer)

  • 作用:词法分析器(Tokenizer)负责将输入的原始字符串(比如 "10 - 3 * 2")分解成一个个有意义的最小单元,即令牌(Token).
  • 设计:Tokenizer 实现了 Iterator trait,这让它可以像一个流一样,按需惰性地生成令牌.它会处理数字、运算符和括号等,并跳过空格.scan_number 方法负责连续读取数字,而 scan_operator 则负责识别单个字符的运算符.

2. 令牌和优先级 (Token & Precedence)

  • 作用:Token 枚举定义了所有可能的令牌类型.每个令牌不仅代表一个符号,还包含了重要的元数据.
  • 设计:
    • is_operator():简单判断一个令牌是否为运算符.
    • certain_priority():返回每个运算符的优先级.例如,乘除的优先级高于加减.
    • associativity():定义运算符的结合性,即计算方向(从左到右或从右到左).例如,加减是左结合的,幂运算(^)是右结合的.
    • compute():执行具体的计算操作.

3. 表达式解析器 (Pratt Parser)

  • 作用:核心的解析逻辑,它使用 Pratt 解析算法,一个基于运算符优先级的递归下降解析器.

  • 设计:

    • Expr 结构体持有 Tokenizer可偷看迭代器(Peekable Iterator),这使得在不消耗令牌的情况下检查下一个令牌成为可能,这是 Pratt 算法的关键.

    • compute_atom():这是递归的基石.它只处理最基本的“原子”表达式:单个数字被括号包围的子表达式.当遇到括号时,它会递归调用 compute_expression 来处理括号内的内容.

    • compute_expression():这是核心的循环和递归部分.它遵循以下逻辑:

      1. 先获取左侧的原子值.
      2. 进入一个循环,检查下一个令牌.
      3. 如果下一个令牌是优先级足够高的运算符,它会递归调用自身来处理右边的子表达式.
      4. 通过给递归调用传入更高的最小优先级(min_precedence),确保了高优先级的运算先于低优先级运算被处理.
      5. 对于左结合的运算符(如 +),它会增加优先级,强制递归调用提前返回,从而让当前的循环先完成计算,确保从左到右的顺序.
      • eval():作为公共入口,它调用 compute_expression 并检查整个表达式是否被完全解析,防止多余的字符.

整个设计通过 “职责分离”(词法分析器负责生成令牌,解析器负责组合令牌)和 “相互递归”(compute_atomcompute_expression 相互调用)的方式,优雅地实现了对复杂表达式的求值.

2

3 多版本控制mvcc

About

some tiny learning projects in Rust

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 85.8%
  • Python 14.2%