ping.rs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. //! The assignment command parser.
  2. //!
  3. //! This can parse arbitrary input, giving the user to be assigned.
  4. //!
  5. //! The grammar is as follows:
  6. //!
  7. //! ```text
  8. //! Command: `@bot ping <team>`.
  9. //! ```
  10. use crate::error::Error;
  11. use crate::token::{Token, Tokenizer};
  12. use std::fmt;
  13. #[derive(PartialEq, Eq, Debug)]
  14. pub struct PingCommand {
  15. pub team: String,
  16. }
  17. #[derive(PartialEq, Eq, Debug)]
  18. pub enum ParseError {
  19. ExpectedEnd,
  20. NoTeam,
  21. }
  22. impl std::error::Error for ParseError {}
  23. impl fmt::Display for ParseError {
  24. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  25. match self {
  26. ParseError::ExpectedEnd => write!(f, "expected end of command"),
  27. ParseError::NoTeam => write!(f, "no team specified"),
  28. }
  29. }
  30. }
  31. impl PingCommand {
  32. pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result<Option<Self>, Error<'a>> {
  33. let mut toks = input.clone();
  34. if let Some(Token::Word("ping")) = toks.peek_token()? {
  35. toks.next_token()?;
  36. let team = if let Some(Token::Word(team)) = toks.next_token()? {
  37. team.to_owned()
  38. } else {
  39. return Err(toks.error(ParseError::NoTeam));
  40. };
  41. if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? {
  42. toks.next_token()?;
  43. *input = toks;
  44. return Ok(Some(PingCommand { team }));
  45. } else {
  46. return Err(toks.error(ParseError::ExpectedEnd));
  47. }
  48. } else {
  49. return Ok(None);
  50. }
  51. }
  52. }
  53. #[cfg(test)]
  54. fn parse<'a>(input: &'a str) -> Result<Option<PingCommand>, Error<'a>> {
  55. let mut toks = Tokenizer::new(input);
  56. Ok(PingCommand::parse(&mut toks)?)
  57. }
  58. #[test]
  59. fn test_1() {
  60. assert_eq!(
  61. parse("ping LLVM-icebreakers."),
  62. Ok(Some(PingCommand {
  63. team: "LLVM-icebreakers".into()
  64. }))
  65. );
  66. }
  67. #[test]
  68. fn test_2() {
  69. use std::error::Error;
  70. assert_eq!(
  71. parse("ping foo foo")
  72. .unwrap_err()
  73. .source()
  74. .unwrap()
  75. .downcast_ref(),
  76. Some(&ParseError::ExpectedEnd),
  77. );
  78. }
  79. #[test]
  80. fn test_3() {
  81. use std::error::Error;
  82. assert_eq!(
  83. parse("ping").unwrap_err().source().unwrap().downcast_ref(),
  84. Some(&ParseError::NoTeam),
  85. );
  86. }