写点什么

语法分析 之数字

作者:Miracle
  • 2025-09-23
    四川
  • 本文字数:1404 字

    阅读完需:约 5 分钟

语法分析 之数字

在所有 语法基本算子的解析中,数字是最常见也最麻烦的,简单的数字当然容易, 一个 from_str_radix 就完全 搞定了,但是各种进制的处理 0x20000 0o 1111 0b 类型的处理浮点数的处理 10.2 102.1111f64 1e20 等等更可怕的是,我们有可能为数字指定类型 比如说 rust 的 10i8 00x99999u64 等等


pub fn number_parser<'a,>() -> impl Parser<'a, &'a str, Dynamic, Extra<'a>> + Clone {    let bin = just('0').ignore_then(one_of("bB")).ignore_then(any().filter(|c| *c == '0' || *c == '1',).repeated().at_least(1,)        .collect::<String>(),).map(|s| Dynamic::from(i64::from_str_radix(&s, 2).unwrap()));    let oct = just('0').ignore_then(one_of("oO")).ignore_then(any().filter(|c| ('0'..='7').contains(c,),).repeated().at_least(1,)        .collect::<String>(),).map(|s| Dynamic::from(i64::from_str_radix(&s, 8).unwrap()));    let hex = just('0').ignore_then(one_of("xX")).ignore_then(any().filter(|c: &char| c.is_ascii_hexdigit(),).repeated().at_least(1,)        .collect::<String>(),).map(|s| Dynamic::from(i64::from_str_radix(&s, 16).unwrap()));    let int_part = text::int(10,).from_str::<i64>().unwrapped();    let frac_part = just('.',).ignore_then(text::digits(10,).collect::<String>(),).map(|s| s.parse::<f64>().unwrap() / 10f64.powi(s.len() as i32,),).or_not();    let exp_part = one_of("eE",).ignore_then(just('+',).to(1,).or(just('-',).to(-1,),).or_not().map(|opt| opt.unwrap_or(1,),).then(text::int(10,).from_str::<i32>().unwrapped(),),).map(|(sign, exp,)| sign as f64 * exp as f64,).or_not();
let decimal = int_part.then(frac_part,).then(exp_part,).map(|((int, frac,), exp,)| { if frac.is_some() || exp.is_some() { let frac_val = frac.unwrap_or(0.0,); let exp_val = exp.unwrap_or(0.0,); Dynamic::from((int as f64 + frac_val) * 10f64.powf(exp_val,)) } else { Dynamic::from(int) } }); bin.or(oct,).or(hex,).or(decimal)
复制代码


}上面这段代码。可以解析出不同的数字量。大家可以看到包括呢?B 开头的。O 开头。8 斤 x 开头的 16 进制。大小是无关的。以及不带任何前缀的普通的 10 进制然后如果带小数点败坏了小子。然后如果是带有的。e(E) 的。那代表了科学计数法


看起来已经很完善了吧?但是在实践中,这个解析器还有一个最大的问题。就是在 rust 和其他的现代的编程语言。为了指定文字量的类型,我们还可以在文字在后面加上一个。后缀比如说 u16 I8,i32 等等。这样我们可以在写代码的时候就规定了。这个数据的类型。这样便于编译器。方便的进行处理和优化。当然也可以不写,不写你看按照我们刚才这个的话,那么不写所有的整数都会被默认为是 i64。所有的那个浮点数默认都认为是 f64。


但是如果我们现在想加上这个后缀的支持的话,那我们就不可避免的要在我们编译器中引入类型系统了。,就是比如说你看现在我们 lat a = 123。这个时候我们可以去做这个赋值。我们知道 123 是个整数,但是不知道它具体是什么样的整数,不过没关系。作为一个编译器时候,作为一个动态类型的编译器。是可以工作的,所以我们把类型这一步放到最后。

用户头像

Miracle

关注

三十年资深码农 2019-10-25 加入

还未添加个人简介

评论

发布
暂无评论
语法分析 之数字_Miracle_InfoQ写作社区