天天看點

程式小白學Rust-----day01

 一、緒論

  隻是記錄學習rust的第一天,不是第一天接觸rust。今天看了b站上一個up主講解nom的視訊,我覺得講得比較好(在為數不多的rust教學視訊裡),視訊兩個小時還有一點沒看完,裡面的内容還是非常紮實的,需要消化一下。

附上視訊的位址https://www.bilibili.com/video/BV1UK4y157BP?t=5572,

下面講解一下今天學的知識。

二、知識點

  1.取String類型。這個是最簡單的解析,隻需要去掉字元串中的引号即可,最後取需要的值就行了

//"a"=x~rust"
fn extra_kv(input:&str)->IResult<&str,(&str,&str)>{
    let (input,(_,k,_,_,_,v))=tuple((
        tag("\""),
        key,
        take_until("\""),
        tag("\""),
        tag("="),
        key,
    )
    )(input)?;
    //println!("out:{:?}",out);//("\"", "a", "", "\"", "=", "x")
    Ok((input,(k,v)))
}

#[test]
fn test_extra_kv(){
    //r#  #代表這裡面的字元串就是這樣,不存在什麼轉義字元這些
    let input=r#""a"=x~rust"#;
    let (input,(k,v))=extra_kv(input).unwrap();
    assert_eq!("~rust",input);
    assert_eq!("a",k);
    assert_eq!("x",v);
}
           

2.取array類型。這個有點低端,當時還不會識别“[”,因為他隻有字元串開頭和結尾有,無法放到

separated_list0中,下面的代碼講了怎麼把"["也消耗掉      
fn extra_arr(input:&str)->IResult<&str,Vec<&str>>{
    let (input,out)=separated_list0(
    //将字元串按逗号分開,然後用tuple處理每個分開後的子串
        tag(","),
          tuple((
              multispace0,
              tag("\""),
              key,
              take_until("\""),
              tag("\""),
          )),
    )(input)?;
    //println!("out={:?}",out);//[(" ", "\"", "a", "", "\""), ("", "\"", "b", "", "\""), ("", "\"", "c", "", "\"")]
    let mut value=vec![];
    for (_,_,v,_,_,) in out{
        value.push(v);
    }
    Ok((input,value))
}

#[test]
fn test_extra_arr(){
    let input=r#" "a","b","c" "#;
    let (input,values)=extra_arr(input).unwrap();
    assert_eq!(vec!["a","b","c"],values);
}
           

3.取array類型,加強版。其實就是引用了2的代碼,然後給他套在tuple中,仔細看能看懂。

//a=["a","b","c"]
fn step_arr(input:&str)->IResult<&str,Vec<&str>>{
    let sep=separated_list0(
        tag(","),
        tuple((
            multispace0,
            tag("\""),
            key,
            take_until("\""),
            tag("\""),
        )),
    );
    let (input,(_,_,_,values,_,_,_))=tuple((
            multispace0,
            tag("["),
            multispace0,
            sep,
            multispace0,
            tag("]"),
            multispace0,
        ))(input)?;
   // println!("out={:?}",values);
    //out=("", "[", "", [("", "\"", "x", "", "\""), ("", "\"", "y", "", "\""), ("", "\"", "z", "", "\"")], "", "]", "")
    let mut value=vec![];
    for (_,_,v,_,_) in values{
        value.push(v);
    }
    Ok((input,value))
}

#[test]
fn test_step_arr(){
    let input=r#"["x","y","z"]"#;
    let (input,val)=step_arr(input).unwrap();
    assert_eq!(vec!["x","y","z"],val);
}
           

4.混合型。這個就是解決字元串中有可能是數組有可能是String類型的問題,但是字元串中隻能存在兩種中的一種,還沒解決兩個類型混合在一起解析,看明天能不能解決吧

fn extra_arr_string(input:&str)->IResult<&str,(&str,Vec<&str>)>{
    let (input,(k,_,(arr,obj)))=tuple((//k,_,(arr,obj))
            key,
            tag("="),
            tuple((opt(step_arr),opt(extra_obj))),
        ))(input)?;
    //println!("out={:?}",out);
    println!("arr={:?}",arr);
    println!("obj={:?}",obj);
    let mut value=vec![];
    if let Some(a)=arr{
        for v in a{
            value.push(v);
        }
    }
    if let Some(obj)=obj{
        value.push(obj)
    }
    Ok((input,(" ",value)))
}

#[test]
fn test_extra_arr_string(){
    let input=r#"a=["x","y","z"]"#;
    let (input,(k,v))=extra_arr_string(input).unwrap();
    assert_eq!(vec!["x","y","z"],v);
}

#[test]
fn test_extra_arr_string2(){
    let input2=r#"a="x""#;
    let (input2,(k,v))=extra_arr_string(input2).unwrap();
    assert_eq!(vec!["x"],v);
}
           

三、小結

    學rust這幫人是真的神仙,研究時間複雜度毫秒已經不能滿足他們了,已經在思考把程式跑到微秒了,這還是我無法觸及的。通過今天視訊的學習,nom在腦子裡已經有那麼回事了,現在就是逐漸處理更複雜的字元串了。