// Copyright (C) 2024 Bellande Architecture Mechanism Research Innovation Center, Ronaldson Bellande // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see . use crate::utilities::Token; pub struct Lexer { input: Vec, position: usize, } impl Lexer { pub fn new(input: String) -> Self { Lexer { input: input.chars().collect(), position: 0, } } fn next_token(&mut self) -> Option { self.skip_whitespace(); if self.position >= self.input.len() { return None; } match self.input[self.position] { '=' => { self.position += 1; Some(Token::Assignment) } '|' => { self.position += 1; Some(Token::Pipe) } '>' => { self.position += 1; Some(Token::Redirect(">".to_string())) } '<' => { self.position += 1; Some(Token::Redirect("<".to_string())) } '(' => { self.position += 1; Some(Token::LeftParen) } ')' => { self.position += 1; Some(Token::RightParen) } ';' => { self.position += 1; Some(Token::Semicolon) } '\n' => { self.position += 1; Some(Token::NewLine) } '&' => { self.position += 1; Some(Token::Ampersand) } '"' => Some(self.read_string()), _ => Some(self.read_word()), } } fn skip_whitespace(&mut self) { while self.position < self.input.len() && self.input[self.position].is_whitespace() { self.position += 1; } } fn read_word(&mut self) -> Token { let start = self.position; while self.position < self.input.len() && !self.input[self.position].is_whitespace() && !matches!( self.input[self.position], '=' | '|' | '>' | '<' | '(' | ')' | ';' | '&' | '\n' ) { self.position += 1; } let word: String = self.input[start..self.position].iter().collect(); match word.as_str() { "if" => Token::If, "then" => Token::Then, "else" => Token::Else, "fi" => Token::Fi, "while" => Token::While, "for" => Token::For, "do" => Token::Do, "done" => Token::Done, "in" => Token::In, _ => Token::Word(word), } } fn read_string(&mut self) -> Token { self.position += 1; // Skip opening quote let start = self.position; while self.position < self.input.len() && self.input[self.position] != '"' { self.position += 1; } let result = Token::Word(self.input[start..self.position].iter().collect()); self.position += 1; // Skip closing quote result } } impl Iterator for Lexer { type Item = Token; fn next(&mut self) -> Option { self.next_token() } }