theultraman20

lex.rs

Jun 30th, 2024
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.79 KB | None | 0 0
  1. use crate::vm::VmError;
  2. use TokenType::*;
  3. use strum_macros::FromRepr;
  4.  
  5. #[derive(Debug, Copy, Clone)]
  6. pub struct Token<'a> {
  7.    pub kind: TokenType,
  8.    pub line_num: usize,
  9.    //How to make this an iterator over
  10.    pub content: &'a str
  11. }
  12.  
  13.  
  14. #[derive(Debug, FromRepr, Copy, Clone, PartialEq)]
  15. pub enum TokenType {
  16.     LeftParen, RightParen,
  17.     LeftBrace, RightBrace,
  18.     Comma, Dot, Minus, Plus,
  19.     Semicolon, Slash, Star,
  20.     // One or two character s.
  21.     Bang, BangEqual,
  22.     Equal, EqualEqual,
  23.     Greater, GreaterEqual,
  24.     Less, LessEqual,
  25.     // Literals; Might change the implementation of these later
  26.     //to utilize the way Clox stores literals
  27.     Identifier, Str, Number,
  28.     // Keywords.
  29.     And, Class, Else, False,
  30.     For, Fun, If, Nil, Or,
  31.     Print, Return, Super, This,
  32.     True, Var, While,
  33.  
  34.     //Use Blank instead of None
  35.     Newline, Eof, Blank
  36. }
  37.  
  38.  
  39.  
  40. pub fn lex(source: &str) -> Result<Vec<Token>, VmError> {
  41.     let mut line_num = 0;
  42.     let mut iter = source.chars().peekable();
  43.  
  44.     let mut tokens = Vec::new();
  45.     let mut curr_idx: usize = 0;
  46.  
  47.     while let Some(c) = iter.next() {
  48.  
  49.         if c.is_whitespace() {
  50.             if c == '\n' { line_num += 1; }
  51.             curr_idx += 1;
  52.             continue;
  53.         }
  54.  
  55.         assert_eq!(source.as_bytes()[curr_idx] as char, c);
  56.  
  57.         //Handle compile time errors later
  58.         //who needs error handling anyways
  59.         let start_idx = curr_idx;
  60.  
  61.         let token_type = match c {
  62.  
  63.             '>' => match iter.peek() {
  64.                 Some('=') => { iter.next(); curr_idx += 1; GreaterEqual }
  65.                 _ => Greater
  66.             }
  67.  
  68.             '<' => match iter.peek() {
  69.                 Some('=') => { iter.next(); curr_idx += 1; LessEqual }
  70.                 _ => Less
  71.             }
  72.  
  73.             '=' => match iter.peek() {
  74.                 Some('=') => { iter.next(); curr_idx += 1; EqualEqual }
  75.                 _ => Equal
  76.             }
  77.  
  78.  
  79.             '!' => match iter.peek() {
  80.                 Some('=') => { iter.next(); curr_idx += 1; BangEqual }
  81.                 _ => Bang
  82.             }
  83.  
  84.             '+' => Plus,
  85.             '-' => Minus,
  86.             '*' => Star,
  87.            
  88.             '/' => match iter.peek() {
  89.                 Some(&'/') => {
  90.                     while iter.next() != Some('\n') {};
  91.                     line_num += 1;
  92.                     continue;
  93.                 }
  94.                
  95.                 _ => Slash
  96.             }
  97.  
  98.             '(' => LeftParen,
  99.             ')' => RightParen,
  100.             '{' => LeftBrace,
  101.             '}' => RightBrace,
  102.             ',' => Comma,
  103.             '.' => Dot,
  104.             ';' => Semicolon,
  105.            
  106.             '\"' => {
  107.                 iter.next();
  108.                 curr_idx += 1;
  109.  
  110.                 //Might crash if you get to the end
  111.                 let chr = iter.next();
  112.                 while chr.is_some() && chr != Some('\"') {
  113.                     curr_idx += 1;            
  114.                 }
  115.  
  116.                 curr_idx += 1;
  117.  
  118.                 //Do nothing with it for now
  119.  
  120.                 if iter.peek().is_none() {
  121.                     panic!("Hahaha sucker, not gonna tell you what the error here is, \
  122.                             fuck you and good luck debugging lmao");
  123.                 }
  124.  
  125.                 Str
  126.             }
  127.  
  128.             //Implement later
  129.             c if c.is_ascii_digit() => {
  130.  
  131.                 //Meh whatever
  132.                 while let Some(_digit) = iter.peek().unwrap().to_digit(10) {
  133.                     iter.next();
  134.                     curr_idx += 1;
  135.                 }
  136.  
  137.                 if iter.peek() == Some(&'.') {
  138.                     iter.next();
  139.                     curr_idx += 1;
  140.                 }
  141.  
  142.                 while let Some(_digit) = iter.peek().unwrap().to_digit(10) {
  143.                     iter.next();
  144.                     curr_idx += 1;
  145.                 }
  146.  
  147.                 Number
  148.             }
  149.  
  150.  
  151.             c if c.is_alphabetic() || c == '_' => {
  152.                 let mut lexeme = String::from(c);
  153.  
  154.                 while let Some(c) = iter.peek() {
  155.                     if (*c).is_alphabetic() || (*c) == '_' {
  156.                         lexeme.push(*c);
  157.                         iter.next();
  158.                         curr_idx += 1;
  159.  
  160.                     } else {
  161.                         break;
  162.                     }
  163.                 }
  164.  
  165.  
  166.                 match lexeme.as_str() {
  167.                     "and" => And,
  168.                     "class" => Class,
  169.                     "else" => Else,
  170.                     "false" => False,
  171.                     "for" => For,              
  172.                     "fun" => Fun,
  173.                     "if" => If,                
  174.                     "nil" => Nil,                    
  175.                     "or" => Or,                    
  176.                     "print" => Print,                    
  177.                     "return" => Return,                    
  178.                     "super" => Super,                  
  179.                     "this" => This,
  180.                     "true" => True,                    
  181.                     "var" => Var,                  
  182.                     "while" => While,
  183.                     //idfk how we're gonna handle strings lol
  184.                     _ => Identifier
  185.                 }
  186.             }
  187.  
  188.             _ => panic!()
  189.         };
  190.  
  191.         curr_idx += 1;
  192.  
  193.         let token = Token {
  194.             kind: token_type,
  195.             line_num: line_num,
  196.             content: &source[start_idx..curr_idx]
  197.         };
  198.  
  199.  
  200.         println!("{}\t{:?}", token.content, token.kind);
  201.  
  202.         tokens.push(token);
  203.     }
  204.  
  205.  
  206.     //Must alter once you start reading into multiple chunks
  207.     tokens.push(Token {
  208.         kind: Eof,
  209.         line_num: line_num,
  210.         content: ""
  211.     });
  212.  
  213.     Ok(tokens)
  214. }
Add Comment
Please, Sign In to add comment