Guest User

Untitled

a guest
Jul 30th, 2024
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 2.83 KB | None | 0 0
  1. mod tokens {
  2.     use std::{
  3.         char,
  4.         iter::{Filter, Peekable},
  5.     };
  6.  
  7.     use thiserror::Error;
  8.  
  9.     #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  10.     pub enum TokenType {
  11.         Number,
  12.         Plus,
  13.         Minus,
  14.         Divide,
  15.         Multiply,
  16.         OpenParen,
  17.         CloseParen,
  18.     }
  19.  
  20.     #[derive(Debug, PartialEq, Eq, Clone)]
  21.     pub struct Token {
  22.         tok_type: TokenType,
  23.         text: String,
  24.     }
  25.  
  26.     impl Token {
  27.         pub fn tok_type(&self) -> TokenType {
  28.             self.tok_type
  29.         }
  30.  
  31.         pub fn text(&self) -> &str {
  32.             &self.text
  33.         }
  34.     }
  35.  
  36.     pub struct Lexer<I>
  37.     where
  38.         I: Iterator<Item = char>,
  39.     {
  40.         inner: Peekable<Filter<I, fn(&char) -> bool>>,
  41.     }
  42.  
  43.     impl<I> Lexer<I>
  44.     where
  45.         I: Iterator<Item = char>,
  46.     {
  47.         pub fn new(inner: I) -> Self {
  48.             Lexer {
  49.                 inner: inner.filter(Self::whitespace_filter).peekable(),
  50.             }
  51.         }
  52.  
  53.         fn whitespace_filter(c: &char) -> bool {
  54.             !c.is_whitespace()
  55.         }
  56.  
  57.         fn next_inner(&mut self) -> <Self as Iterator>::Item {
  58.             match self.inner.peek().unwrap() {
  59.                 '(' => Ok(Token {
  60.                     tok_type: TokenType::OpenParen,
  61.                     text: self.inner.next().unwrap().to_string(),
  62.                 }),
  63.                 ')' => Ok(Token {
  64.                     tok_type: TokenType::CloseParen,
  65.                     text: self.inner.next().unwrap().to_string(),
  66.                 }),
  67.                 '+' => Ok(Token {
  68.                     tok_type: TokenType::Plus,
  69.                     text: self.inner.next().unwrap().to_string(),
  70.                 }),
  71.                 '-' => Ok(Token {
  72.                     tok_type: TokenType::Minus,
  73.                     text: self.inner.next().unwrap().to_string(),
  74.                 }),
  75.                 '*' => Ok(Token {
  76.                     tok_type: TokenType::Multiply,
  77.                     text: self.inner.next().unwrap().to_string(),
  78.                 }),
  79.                 '/' => Ok(Token {
  80.                     tok_type: TokenType::Divide,
  81.                     text: self.inner.next().unwrap().to_string(),
  82.                 }),
  83.                 c => Err(TokenizationError::UnexpectedCharacter(*c)),
  84.             }
  85.         }
  86.     }
  87.  
  88.     #[derive(Debug, Error)]
  89.     pub enum TokenizationError {
  90.         #[error("unexpected character: '{0}'")]
  91.         UnexpectedCharacter(char),
  92.     }
  93.  
  94.     impl<I> Iterator for Lexer<I>
  95.     where
  96.         I: Iterator<Item = char>,
  97.     {
  98.         type Item = Result<Token, TokenizationError>;
  99.  
  100.         fn next(&mut self) -> Option<Self::Item> {
  101.             match self.inner.peek() {
  102.                 Some(_) => Some(self.next_inner()),
  103.                 None => None,
  104.             }
  105.         }
  106.     }
  107. }
  108.  
Advertisement
Add Comment
Please, Sign In to add comment