0

尝试做与这个问题类似的事情,除了允许从第二个字符开始使用下划线。不仅仅是骆驼案。

我可以成功地单独测试解析器,但是在更高级别的解析器中组合时,我得到了错误

举个例子:

#![allow(dead_code)]
#[macro_use]

extern crate nom;

use nom::*;

type Bytes<'a> = &'a [u8];

#[derive(Clone,PartialEq,Debug)]
pub enum Statement {
  IF,
  ELSE,
  ASSIGN((String)),
  IDENTIFIER(String),
  EXPRESSION,
}

fn lowerchar(input: Bytes) -> IResult<Bytes, char>{
  if input.is_empty() {
    IResult::Incomplete(Needed::Size(1))
  } else if (input[0] as char)>='a' && 'z'>=(input[0] as char) {
    IResult::Done(&input[1..], input[0] as char)
  } else {
    IResult::Error(error_code!(ErrorKind::Custom(1)))
  }
}

named!(identifier<Bytes,Statement>, map_res!(
    recognize!(do_parse!(
        lowerchar >>
        //alt_complete! is not having the effect it's supposed to so the alternatives need to be ordered from shortest to longest
        many0!(alt!(
            complete!(is_a!("_"))
            | complete!(take_while!(nom::is_alphanumeric))
            )) >> ()
        )),
        |id: Bytes| {
          //println!("{:?}",std::str::from_utf8(id).unwrap().to_string());
          Result::Ok::<Statement, &str>(
            Statement::IDENTIFIER(std::str::from_utf8(id).unwrap().to_string())
            )
        }
        ));

named!(expression<Bytes,Statement>, alt_complete!(
    identifier //=> { |e: Statement| e }
    //| assign_expr //=> { |e: Statement| e }
    | if_expr //=> { |e: Statement| e }
    ));

named!(if_expr<Bytes,Statement>, do_parse!(
    if_statement: preceded!(
      tag!("if"),
      delimited!(tag!("("),expression,tag!(")"))
      ) >>
    //if_statement: delimited!(tag!("("),tag!("hello"),tag!(")")) >>
    if_expr: expression >>
    //else_statement: opt_res!(tag!("else")) >>
    (Statement::IF)
    ));

#[cfg(test)]
mod tests {
  use super::*;
  use IResult::*;
  //use IResult::Done;

  #[test]
  fn ident_token() {
    assert_eq!(identifier(b"iden___ifiers"), Done::<Bytes, Statement>(b"" , Statement::IDENTIFIER("iden___ifiers".to_string())));
    assert_eq!(identifier(b"iden_iFIErs"), Done::<Bytes, Statement>(b"" , Statement::IDENTIFIER("iden_iFIErs".to_string())));
    assert_eq!(identifier(b"Iden_iFIErs"), Error(ErrorKind::Custom(1))); // Supposed to fail since not valid
    assert_eq!(identifier(b"_den_iFIErs"), Error(ErrorKind::Custom(1))); // Supposed to fail since not valid
  }

  #[test]
  fn if_token() {
    assert_eq!(if_expr(b"if(a)a"), Error(ErrorKind::Alt)); // Should have passed
    assert_eq!(if_expr(b"if(hello)asdas"), Error(ErrorKind::Alt)); // Should have passed
  }

  #[test]
  fn expr_parser() {
    assert_eq!(expression(b"iden___ifiers"), Done::<Bytes, Statement>(b"" , Statement::IDENTIFIER("iden___ifiers".to_string())));
    assert_eq!(expression(b"if(hello)asdas"), Error(ErrorKind::Alt)); // Should have been able to recognise an IF statement via expression parser
  }
}
4

0 回答 0