#!/usr/bin/env rust-script
//! # Thepg: A Comprehensive Parser Generator in Rust
//!
//! **Thepg** is a powerful parser generator that processes Extended Backus–Naur Form (ENBF) grammars
//! and produces robust, compile-ready Rust code for parsing based on the provided grammar.
//!
//! ## Features
//! - Supports LL(1) and LL(k) parsing strategies
//! - Generates lexing-capable parsers with support for identifiers and literals
//! - Outputs well-structured Rust code in a single file
//! - Constructs Abstract Syntax Trees (AST) during the parsing process
//! - Comprehensive error handling with informative messages
//! - User-friendly command-line interface using `clap`
//!
//! ## Usage
//! To generate a parser, run the following command:
//! 
//! ```bash
//! cargo run --release -- <grammar.enbf> -o <output_file.rs> --grammar-type <LL1|LLk> --lookahead <k>
//! ```
//! 
//! - Replace `<grammar.enbf>` with your ENBF grammar file.
//! - Replace `<output_file.rs>` with your desired output Rust file name.
//! - Use `--grammar-type` to specify the parsing strategy (`LL1` or `LLk`).
//! - Use `--lookahead` to define the number of tokens to look ahead (applicable for `LLk` parsing).
//!
//! ## Example
//! Given the following `arithmetic.enbf` grammar:
//!
//! ```enbf
//! # arithmetic.enbf
//! Expr ::= Term ExprPrime
//! ExprPrime ::= "+" Term ExprPrime | "-" Term ExprPrime | ε
//! Term ::= Factor TermPrime
//! TermPrime ::= "*" Factor TermPrime | "/" Factor TermPrime | ε
//! Factor ::= "(" Expr ")" | "id" | "number"
//! ```
//!
//! Generate the parser as follows:
//!
//! ```bash
//! cargo run --release -- arithmetic.enbf -o arithmetic_parser.rs --grammar-type LL1
//! ```
//!
//! The above command will create `arithmetic_parser.rs` containing the lexer, parser, and AST definitions
//! based on the provided grammar.
//!
//! ## Testing
//! Execute the embedded test cases using Cargo:
//!
//! ```bash
//! cargo test
//! ```
//!
//! ## License
//! MIT License. See `LICENSE` for details.

use clap::{Arg, ArgAction, Command};
use regex::Regex;
use std::collections::{HashMap, HashSet, VecDeque};
use std::env;
use std::fs;
use std::io::{self, Write};
use std::path::Path;

/// Represents various parsing errors.
#[derive(Debug)]
enum ParseError {
    /// Unexpected token encountered during parsing.
    UnexpectedToken {
        expected: Vec<String>,
        found: String,
        position: usize,
    },
    /// Invalid grammar structure.
    InvalidGrammar(String),
    /// Lexer encountered an error.
    LexerError(String),
}

impl std::fmt::Display for ParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ParseError::UnexpectedToken { expected, found, position } => {
                write!(
                    f,
                    "Unexpected token at position {}: expected {:?}, found {}",
                    position, expected, found
                )
            },
            ParseError::InvalidGrammar(msg) => write!(f, "Invalid grammar: {}", msg),
            ParseError::LexerError(msg) => write!(f, "Lexer error: {}", msg),
        }
    }
}

impl std::error::Error for ParseError {}

/// Represents a grammar rule with a head and multiple production bodies.
#[derive(Debug, Clone)]
struct Rule {
    head: String,
    bodies: Vec<Vec<String>>,
}

/// Represents the entire parsed grammar, including rules, terminals, non-terminals, and FIRST/FOLLOW sets.
#[derive(Debug)]
struct Grammar {
    rules: Vec<Rule>,
    terminals: HashSet<String>,
    non_terminals: HashSet<String>,
    first_sets: HashMap<String, HashSet<String>>,
    follow_sets: HashMap<String, HashSet<String>>,
}

impl Grammar {
    /// Parses the ENBF grammar from a string input.
    fn parse(enbf: &str) -> Result<Self, ParseError> {
        let mut rules = Vec::new();
        let mut non_terminals = HashSet::new(); // To store non-terminals
        let mut terminals = HashSet::new();

        for (line_no, line) in enbf.lines().enumerate() {
            let line = line.trim();
            if line.is_empty() || line.starts_with("#") {
                continue;
            }
            let parts: Vec<&str> = line.split("::=").collect();
            if parts.len() != 2 {
                return Err(ParseError::InvalidGrammar(format!(
                    "Invalid rule at line {}",
                    line_no + 1
                )));
            }
            let head = parts[0].trim().to_string();
            non_terminals.insert(head.clone());
            let bodies_str = parts[1];
            let bodies: Vec<Vec<String>> = bodies_str
                .split('|')
                .map(|body| body.trim().split_whitespace().map(|s| s.to_string()).collect())
                .collect();
            rules.push(Rule { head, bodies });
        }

        // Identify terminals (symbols not defined as non-terminals and not ε)
        for rule in &rules {
            for body in &rule.bodies {
                for symbol in body {
                    if !symbol.starts_with("<") && !symbol.ends_with(">")
                        && !symbol.starts_with("\"") && !symbol.starts_with("'")
                        && symbol != "ε"
                    {
                        terminals.insert(symbol.clone());
                    }
                }
            }
        }

        // Remove non-terminals from terminals set
        for nt in &non_terminals {
            terminals.remove(nt);
        }

        let mut grammar = Grammar {
            rules,
            terminals,
            non_terminals,
            first_sets: HashMap::new(),
            follow_sets: HashMap::new(),
        };

        grammar.compute_first_sets()?;
        grammar.compute_follow_sets()?;

        Ok(grammar)
    }

    /// Computes FIRST sets for all non-terminals using a queue-based iterative approach.
    fn compute_first_sets(&mut self) -> Result<(), ParseError> {
        // Initialize FIRST sets
        for nt in &self.non_terminals {
            self.first_sets.insert(nt.clone(), HashSet::new());
        }

        let mut queue: VecDeque<String> = VecDeque::new();

        // Initialize queue with all non-terminals
        for nt in &self.non_terminals {
            queue.push_back(nt.clone());
        }

        while let Some(nt) = queue.pop_front() {
            let mut updated = false;
            let mut nt_first = self.first_sets.get(&nt).unwrap().clone();

            for rule in self.rules.iter().filter(|r| r.head == nt) {
                for body in &rule.bodies {
                    let mut can_produce_epsilon = true;
                    for symbol in body {
                        if self.non_terminals.contains(symbol) {
                            let symbol_first = &self.first_sets[symbol];
                            let before = nt_first.len();
                            nt_first.extend(symbol_first.iter().filter(|&&s| s != "ε").cloned());
                            let after = nt_first.len();
                            if after > before {
                                updated = true;
                            }
                            if !symbol_first.contains("ε") {
                                can_produce_epsilon = false;
                                break;
                            }
                        } else {
                            let before = nt_first.len();
                            nt_first.insert(symbol.clone());
                            let after = nt_first.len();
                            if after > before {
                                updated = true;
                            }
                            can_produce_epsilon = false;
                            break;
                        }
                    }
                    if can_produce_epsilon {
                        if nt_first.insert("ε".to_string()) {
                            updated = true;
                        }
                    }
                }
            }

            if updated {
                self.first_sets.insert(nt.clone(), nt_first.clone());
                // Enqueue dependent non-terminals
                for rule in &self.rules {
                    if rule.bodies.iter().any(|body| body.contains(&nt)) {
                        if !queue.contains(&rule.head) {
                            queue.push_back(rule.head.clone());
                        }
                    }
                }
            }
        }

        Ok(())
    }

    /// Computes FOLLOW sets for all non-terminals using a queue-based iterative approach.
    fn compute_follow_sets(&mut self) -> Result<(), ParseError> {
        // Initialize FOLLOW sets
        for nt in &self.non_terminals {
            self.follow_sets.insert(nt.clone(), HashSet::new());
        }

        // Assume the first rule's head is the start symbol
        if let Some(start_rule) = self.rules.first() {
            self.follow_sets
                .get_mut(&start_rule.head)
                .unwrap()
                .insert("$".to_string()); // End marker
        } else {
            return Err(ParseError::InvalidGrammar(
                "No rules found in the grammar.".to_string(),
            ));
        }

        let mut queue: VecDeque<String> = VecDeque::new();
        // Enqueue all non-terminals initially
        for nt in &self.non_terminals {
            queue.push_back(nt.clone());
        }

        while let Some(nt) = queue.pop_front() {
            let mut nt_follow = self.follow_sets.get(&nt).unwrap().clone();
            let mut updated = false;

            for rule in &self.rules {
                for body in &rule.bodies {
                    for i in 0..body.len() {
                        if &body[i] == nt {
                            // Compute FIRST of the remaining symbols in the production
                            let mut first_of_suffix = HashSet::new();
                            let mut can_add_follow = true;
                            for sym in body.iter().skip(i + 1) {
                                if self.non_terminals.contains(sym) {
                                    let sym_first = &self.first_sets[sym];
                                    first_of_suffix.extend(sym_first.iter().filter(|&&s| s != "ε").cloned());
                                    if !sym_first.contains("ε") {
                                        can_add_follow = false;
                                        break;
                                    }
                                } else {
                                    first_of_suffix.insert(sym.clone());
                                    can_add_follow = false;
                                    break;
                                }
                            }
                            // Add FIRST(suffix) \ {ε} to FOLLOW(nt)
                            let before = nt_follow.len();
                            nt_follow.extend(first_of_suffix.iter().cloned());
                            let after = nt_follow.len();
                            if after > before {
                                updated = true;
                            }
                            // If FIRST(suffix) contains ε, add FOLLOW(head) to FOLLOW(nt)
                            if can_add_follow {
                                let head_follow = &self.follow_sets[&rule.head];
                                let before = nt_follow.len();
                                nt_follow.extend(head_follow.iter().cloned());
                                let after = nt_follow.len();
                                if after > before {
                                    updated = true;
                                }
                            }
                        }
                    }
                }
            }

            if updated {
                self.follow_sets.insert(nt.clone(), nt_follow.clone());
                // Enqueue dependent non-terminals
                for rule in &self.rules {
                    if rule.bodies.iter().any(|body| body.contains(&nt)) {
                        if !queue.contains(&rule.head) {
                            queue.push_back(rule.head.clone());
                        }
                    }
                }
            }
        }

        Ok(())
    }

    /// Determines the FIRST set for a given production body.
    fn first_of_body(body: &Vec<String>, first_sets: &HashMap<String, HashSet<String>>) -> Option<HashSet<String>> {
        let mut first = HashSet::new();
        for symbol in body {
            if symbol == "ε" {
                first.insert("ε".to_string());
                return Some(first);
            }
            if let Some(sym_first) = first_sets.get(symbol) {
                first.extend(sym_first.iter().filter(|&&s| s != "ε").cloned());
                if !sym_first.contains("ε") {
                    return Some(first);
                }
            } else {
                first.insert(symbol.clone());
                return Some(first);
            }
        }
        first.insert("ε".to_string());
        Some(first)
    }

    /// Checks if a production body can produce ε (epsilon).
    fn body_can_produce_epsilon(body: &Vec<String>, first_sets: &HashMap<String, HashSet<String>>) -> bool {
        body.iter().all(|symbol| {
            if let Some(sym_first) = first_sets.get(symbol) {
                sym_first.contains("ε")
            } else {
                false
            }
        })
    }

    /// Sanitizes token names to be Rust-compatible by replacing or removing invalid characters.
    fn sanitize_token(token: &str) -> String {
        token
            .trim_matches('"')
            .trim_matches('\'')
            .replace("+", "PLUS")
            .replace("-", "MINUS")
            .replace("*", "STAR")
            .replace("/", "SLASH")
            .replace("(", "L_PAREN")
            .replace(")", "R_PAREN")
            .replace("{", "L_BRACE")
            .replace("}", "R_BRACE")
            .replace("[", "L_BRACKET")
            .replace("]", "R_BRACKET")
            .replace(",", "COMMA")
            .replace(";", "SEMICOLON")
            .replace(":", "COLON")
            .replace("<", "")
            .replace(">", "")
            .replace("|", "OR")
            .replace("=", "EQ")
            .replace("!", "EXCLAMATION")
            .replace("?", "QUESTION")
            .replace("#", "HASH")
            .replace("$", "DOLLAR")
            .replace("&", "AMPERSAND")
            .replace("@", "AT")
            .replace("~", "TILDE")
            .replace(".", "DOT")
            .replace("'", "")
            .to_uppercase()
    }

    /// Sanitizes function names to be Rust-compatible by converting to lowercase and replacing invalid characters.
    fn sanitize_func(func: &str) -> String {
        func.to_lowercase()
            .replace("<", "")
            .replace(">", "")
            .replace("-", "_")
            .replace(" ", "_")
    }

    /// Represents the different types of tokens.
    #[derive(Debug, PartialEq, Clone)]
    enum TokenEnum {
        // Fixed symbols
        PLUS,
        MINUS,
        STAR,
        SLASH,
        L_PAREN,
        R_PAREN,
        // Multi-character symbols
        EQ,
        NEQ,
        LEQ,
        GEQ,
        // Pattern-based tokens
        ID(String),
        NUMBER(i32),
        EOF,
    }

    /// The Lexer struct responsible for tokenizing the input string.
    struct Lexer {
        input: Peekable<Chars<'static>>,
        buffer: Vec<TokenEnum>, // Buffer for lookahead
        regex_map: Vec<(Regex, fn(&str) -> TokenEnum)>, // Regex patterns and corresponding token constructors
        current_position: usize, // Current character position in input
    }

    impl Lexer {
        /// Creates a new Lexer instance.
        fn new(input: &str) -> Self {
            let input_owned = input.to_string();
            let input_static: &'static str = Box::leak(input_owned.into_boxed_str());
            let mut regex_map = Vec::new();
            // Order matters: longer patterns first
            regex_map.push((
                Regex::new(r"^==").unwrap(),
                |_| TokenEnum::EQ,
            ));
            regex_map.push((
                Regex::new(r"^!=").unwrap(),
                |_| TokenEnum::NEQ,
            ));
            regex_map.push((
                Regex::new(r"^<=").unwrap(),
                |_| TokenEnum::LEQ,
            ));
            regex_map.push((
                Regex::new(r"^>=").unwrap(),
                |_| TokenEnum::GEQ,
            ));
            regex_map.push((
                Regex::new(r"^\+").unwrap(),
                |_| TokenEnum::PLUS,
            ));
            regex_map.push((
                Regex::new(r"^\-").unwrap(),
                |_| TokenEnum::MINUS,
            ));
            regex_map.push((
                Regex::new(r"^\*").unwrap(),
                |_| TokenEnum::STAR,
            ));
            regex_map.push((
                Regex::new(r"^\/").unwrap(),
                |_| TokenEnum::SLASH,
            ));
            regex_map.push((
                Regex::new(r"^\(").unwrap(),
                |_| TokenEnum::L_PAREN,
            ));
            regex_map.push((
                Regex::new(r"^\)").unwrap(),
                |_| TokenEnum::R_PAREN,
            ));
            // Identifiers
            regex_map.push((
                Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*").unwrap(),
                |s| TokenEnum::ID(s.to_string()),
            ));
            // Numbers
            regex_map.push((
                Regex::new(r"^\d+").unwrap(),
                |s| TokenEnum::NUMBER(s.parse().unwrap()),
            ));

            Lexer {
                input: input_static.chars().peekable(),
                buffer: Vec::new(),
                regex_map,
                current_position: 0,
            }
        }

        /// Retrieves the next token from the buffer or lexer.
        fn next_token(&mut self) -> TokenEnum {
            if !self.buffer.is_empty() {
                self.buffer.remove(0)
            } else {
                self.lex_next_token()
            }
        }

        /// Peeks `k` tokens ahead without consuming them.
        fn peek(&mut self, k: usize) -> Vec<TokenEnum> {
            while self.buffer.len() < k {
                let token = self.lex_next_token();
                if token == TokenEnum::EOF {
                    break;
                }
                self.buffer.push(token);
            }
            self.buffer.iter().cloned().take(k).collect()
        }

        /// Lexes the next token using regex patterns.
        fn lex_next_token(&mut self) -> TokenEnum {
            let remaining: String = self.input.clone().collect();
            for (regex, constructor) in &self.regex_map {
                if let Some(mat) = regex.find(&remaining) {
                    let matched_str = mat.as_str();
                    let token = constructor(matched_str);
                    // Advance the input by the length of the matched string
                    for _ in 0..matched_str.len() {
                        self.input.next();
                        self.current_position += 1;
                    }
                    return token;
                }
            }

            // If no regex matched, handle unknown characters
            if let Some(c) = self.input.next() {
                self.current_position += 1;
                eprintln!("Warning: Unrecognized character '{}'", c);
                TokenEnum::EOF
            } else {
                TokenEnum::EOF
            }
        }
    }

    /// Represents an AST Node.
    #[derive(Debug, PartialEq, Clone)]
    enum ASTNode {
        NonTerminal(String),
        Terminal(TokenEnum),
        Identifier(String),
        Number(i32),
    }

    /// The Parser struct responsible for parsing the input and constructing the AST.
    struct ParserStruct<'a> {
        lexer: Lexer,
        current_token: TokenEnum,
        lookahead: Vec<TokenEnum>,
        grammar: &'a Grammar,
        k: usize, // Lookahead size
        position: usize, // Current parsing position
    }

    impl<'a> ParserStruct<'a> {
        /// Creates a new Parser instance with the given input string, grammar, and lookahead size.
        fn new(input: &'a str, grammar: &'a Grammar, k: usize) -> Self {
            let mut lexer = Lexer::new(input);
            let first_token = lexer.next_token();
            ParserStruct {
                lexer,
                current_token: first_token,
                lookahead: Vec::new(),
                grammar,
                k,
                position: 0,
            }
        }

        /// Initiates the parsing process starting from the start symbol.
        fn parse(&mut self) -> Result<ASTNode, ParseError> {
            if let Some(start_rule) = self.grammar.rules.first() {
                let ast = self.parse_non_terminal(&start_rule.head)?;
                if self.current_token == TokenEnum::EOF {
                    Ok(ast)
                } else {
                    Err(ParseError::UnexpectedToken {
                        expected: vec!["EOF".to_string()],
                        found: format!("{:?}", self.current_token),
                        position: self.position,
                    })
                }
            } else {
                Err(ParseError::InvalidGrammar(
                    "No rules defined in the grammar.".to_string(),
                ))
            }
        }

        /// Parses a non-terminal symbol considering LL(k) lookahead.
        fn parse_non_terminal(&mut self, non_terminal: &str) -> Result<ASTNode, ParseError> {
            if let Some(rule) = self.grammar.rules.iter().find(|r| r.head == non_terminal) {
                for body in &rule.bodies {
                    let first_set = first_of_body(body, &self.grammar.first_sets).unwrap();
                    let tokens = self.lexer.peek(self.k);
                    let intersects = self.should_use_production(&first_set, &tokens, non_terminal)?;

                    if intersects || first_set.contains("ε") {
                        return self.parse_production(body);
                    }
                }
                Err(ParseError::UnexpectedToken {
                    expected: vec!["valid production".to_string()],
                    found: format!("{:?}", self.current_token),
                    position: self.position,
                })
            } else {
                Err(ParseError::InvalidGrammar(format!(
                    "Non-terminal '{}' not found in grammar",
                    non_terminal
                )))
            }
        }

        /// Determines whether to use a production based on the FIRST set and lookahead tokens.
        fn should_use_production(
            &self,
            first_set: &HashSet<String>,
            tokens: &Vec<TokenEnum>,
            non_terminal: &str,
        ) -> Result<bool, ParseError> {
            for t in first_set {
                match t.as_str() {
                    "ε" => {
                        let follow_set = &self.grammar.follow_sets[non_terminal];
                        for tok in tokens {
                            if follow_set.contains("$") && *tok == TokenEnum::EOF {
                                return Ok(true);
                            }
                            match tok {
                                TokenEnum::ID(_) => {
                                    if follow_set.contains("id") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::NUMBER(_) => {
                                    if follow_set.contains("number") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::PLUS => {
                                    if follow_set.contains("+") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::MINUS => {
                                    if follow_set.contains("-") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::STAR => {
                                    if follow_set.contains("*") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::SLASH => {
                                    if follow_set.contains("/") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::L_PAREN => {
                                    if follow_set.contains("(") {
                                        return Ok(true);
                                    }
                                }
                                TokenEnum::R_PAREN => {
                                    if follow_set.contains(")") {
                                        return Ok(true);
                                    }
                                }
                                _ => {}
                            }
                        }
                    }
                    "id" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::ID(_))) {
                            return Ok(true);
                        }
                    }
                    "number" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::NUMBER(_))) {
                            return Ok(true);
                        }
                    }
                    "+" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::PLUS)) {
                            return Ok(true);
                        }
                    }
                    "-" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::MINUS)) {
                            return Ok(true);
                        }
                    }
                    "*" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::STAR)) {
                            return Ok(true);
                        }
                    }
                    "/" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::SLASH)) {
                            return Ok(true);
                        }
                    }
                    "(" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::L_PAREN)) {
                            return Ok(true);
                        }
                    }
                    ")" => {
                        if tokens.iter().any(|tok| matches!(tok, TokenEnum::R_PAREN)) {
                            return Ok(true);
                        }
                    }
                    _ => {}
                }
            }
            Ok(false)
        }

        /// Parses a production body and constructs the corresponding AST node.
        fn parse_production(&mut self, body: &Vec<String>) -> Result<ASTNode, ParseError> {
            let mut children = Vec::new();
            for symbol in body {
                if self.grammar.non_terminals.contains(symbol) {
                    let child = self.parse_non_terminal(symbol)?;
                    children.push(child);
                } else {
                    match symbol.as_str() {
                        "+" => {
                            self.eat(TokenEnum::PLUS)?;
                            children.push(ASTNode::Terminal(TokenEnum::PLUS.clone()));
                        }
                        "-" => {
                            self.eat(TokenEnum::MINUS)?;
                            children.push(ASTNode::Terminal(TokenEnum::MINUS.clone()));
                        }
                        "*" => {
                            self.eat(TokenEnum::STAR)?;
                            children.push(ASTNode::Terminal(TokenEnum::STAR.clone()));
                        }
                        "/" => {
                            self.eat(TokenEnum::SLASH)?;
                            children.push(ASTNode::Terminal(TokenEnum::SLASH.clone()));
                        }
                        "(" => {
                            self.eat(TokenEnum::L_PAREN)?;
                            children.push(ASTNode::Terminal(TokenEnum::L_PAREN.clone()));
                        }
                        ")" => {
                            self.eat(TokenEnum::R_PAREN)?;
                            children.push(ASTNode::Terminal(TokenEnum::R_PAREN.clone()));
                        }
                        "id" => {
                            if let TokenEnum::ID(value) = &self.current_token {
                                self.eat(TokenEnum::ID(value.clone()))?;
                                children.push(ASTNode::Identifier(value.clone()));
                            } else {
                                return Err(ParseError::UnexpectedToken {
                                    expected: vec!["id".to_string()],
                                    found: format!("{:?}", self.current_token),
                                    position: self.position,
                                });
                            }
                        }
                        "number" => {
                            if let TokenEnum::NUMBER(value) = self.current_token.clone() {
                                self.eat(TokenEnum::NUMBER(value))?;
                                children.push(ASTNode::Number(value));
                            } else {
                                return Err(ParseError::UnexpectedToken {
                                    expected: vec!["number".to_string()],
                                    found: format!("{:?}", self.current_token),
                                    position: self.position,
                                });
                            }
                        }
                        _ => {
                            return Err(ParseError::InvalidGrammar(format!(
                                "Unknown terminal symbol '{}'",
                                symbol
                            )));
                        }
                    }
                }
            }
            Ok(ASTNode::NonTerminal(body.join(" ")))
        }

        /// Consumes the current token if it matches the expected token.
        fn eat(&mut self, token: TokenEnum) -> Result<(), ParseError> {
            if self.current_token == token {
                self.current_token = self.lexer.next_token();
                self.position += 1;
                Ok(())
            } else {
                Err(ParseError::UnexpectedToken {
                    expected: vec![format!("{:?}", token)],
                    found: format!("{:?}", self.current_token),
                    position: self.position,
                })
            }
        }
    }

    /// Generates Rust code for the parser based on the parsed grammar.
    struct CodeGenerator {
        grammar: Grammar,
        grammar_type: String,
        lookahead: usize,
    }

    impl CodeGenerator {
        /// Creates a new CodeGenerator instance.
        fn new(grammar: &Grammar, grammar_type: &str, lookahead: usize) -> Self {
            CodeGenerator {
                grammar: grammar.clone(),
                grammar_type: grammar_type.to_string(),
                lookahead,
            }
        }

        /// Generates the complete Rust code for the parser.
        fn generate_code(&self, output_file: &str) -> Result<(), String> {
            let mut code = String::new();

            // Header with documentation
            code.push_str("//! # Generated Parser\n");
            code.push_str("//!\n");
            code.push_str("//! This parser was automatically generated by **Thepg**, a Rust-based parser generator.\n");
            code.push_str("//! It is designed to parse inputs based on the provided ENBF grammar.\n");
            code.push_str("//!\n");
            code.push_str("//! ## Features\n");
            code.push_str("//! - Lexer-free parsing\n");
            code.push_str("//! - Supports LL(1) and LL(k) parsing strategies\n");
            code.push_str("//! - Constructs Abstract Syntax Trees (AST)\n");
            code.push_str("//!\n");
            code.push_str("//! ## Usage\n");
            code.push_str("//! ```rust\n");
            code.push_str("//! use crate::Parser;\n");
            code.push_str("//!\n");
            code.push_str("//! fn main() {\n");
            code.push_str("//!     let input = \"your_input_here\";\n");
            code.push_str("//!     let mut parser = Parser::new(input);\n");
            code.push_str("//!     match parser.parse() {\n");
            code.push_str("//!         Ok(ast) => println!(\"Parsing succeeded. AST: {:?}\", ast),\n");
            code.push_str("//!         Err(e) => println!(\"Parsing failed: {}\", e),\n");
            code.push_str("//!     }\n");
            code.push_str("//! }\n");
            code.push_str("//! ```\n");
            code.push_str("//!\n");
            code.push_str("//! ## Example\n");
            code.push_str("//! Given the following grammar:\n");
            code.push_str("//!\n");
            code.push_str("//! ```enbf\n");
            for rule in &self.grammar.rules {
                code.push_str(&format!("{} ::= {}\n", rule.head, rule.bodies.iter().map(|b| b.join(" ")).collect::<Vec<String>>().join(" | ")));
            }
            code.push_str("//! ```\n");
            code.push_str("//!\n");
            code.push_str("//! After generating the parser, you can use it to parse expressions like `id + id * id`.\n");
            code.push_str("//!\n");

            // Token definitions
            code.push_str("#[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("pub enum Token {\n");
            for terminal in &self.grammar.terminals {
                if terminal == "id" {
                    code.push_str("    ID(String),\n");
                } else if terminal == "number" {
                    code.push_str("    NUMBER(i32),\n");
                } else {
                    let tok = sanitize_token(terminal);
                    code.push_str(&format!("    {},\n", tok));
                }
            }
            code.push_str("    EOF,\n");
            code.push_str("}\n\n");

            // Parser struct with documentation
            code.push_str("/// The Parser struct responsible for parsing the input string and constructing the AST.\n");
            code.push_str("#[derive(Debug)]\n");
            code.push_str("pub struct Parser<'a> {\n");
            code.push_str("    lexer: Lexer,\n");
            code.push_str("    current_token: Token,\n");
            code.push_str("    grammar: &'a Grammar,\n");
            code.push_str("    lookahead: usize,\n");
            code.push_str("    position: usize,\n");
            code.push_str("}\n\n");

            // Implement Parser with documentation
            code.push_str("impl<'a> Parser<'a> {\n");
            code.push_str("    /// Creates a new Parser instance with the given input string, grammar, and lookahead size.\n");
            code.push_str("    ///\n");
            code.push_str("    /// # Arguments\n");
            code.push_str("    ///\n");
            code.push_str("    /// * `input` - A string slice that holds the input to be parsed.\n");
            code.push_str("    /// * `grammar` - A reference to the parsed Grammar struct.\n");
            code.push_str("    /// * `lookahead` - The number of tokens to look ahead during parsing.\n");
            code.push_str("    ///\n");
            code.push_str("    /// # Example\n");
            code.push_str("    ///\n");
            code.push_str("    /// ```rust\n");
            code.push_str("    /// let grammar = Grammar::parse(grammar_str).unwrap();\n");
            code.push_str("    /// let mut parser = Parser::new(\"id + id * id\", &grammar, 2);\n");
            code.push_str("    /// ```\n");
            code.push_str("    pub fn new(input: &'a str, grammar: &'a Grammar, lookahead: usize) -> Self {\n");
            code.push_str("        let mut lexer = Lexer::new(input);\n");
            code.push_str("        let first_token = lexer.next_token();\n");
            code.push_str("        Parser {\n");
            code.push_str("            lexer,\n");
            code.push_str("            current_token: first_token,\n");
            code.push_str("            grammar,\n");
            code.push_str("            lookahead,\n");
            code.push_str("            position: 0,\n");
            code.push_str("        }\n");
            code.push_str("    }\n\n");

            // Parsing functions
            for rule in &self.grammar.rules {
                let func_name = sanitize_func(&rule.head);
                code.push_str(&format!("    /// Parses the `{}` non-terminal.\n", rule.head));
                code.push_str(&format!("    pub fn {}(&mut self) -> Result<ASTNode, ParseError> {{\n", func_name));
                code.push_str("        match &self.current_token {\n");

                for body in &rule.bodies {
                    let first_set = first_of_body(body, &self.grammar.first_sets).unwrap();
                    for terminal in &first_set {
                        if terminal != "ε" {
                            let tok = match terminal.as_str() {
                                "+" => "Token::PLUS",
                                "-" => "Token::MINUS",
                                "*" => "Token::STAR",
                                "/" => "Token::SLASH",
                                "(" => "Token::L_PAREN",
                                ")" => "Token::R_PAREN",
                                "id" => "Token::ID(_)".to_string(),
                                "number" => "Token::NUMBER(_)".to_string(),
                                _ => sanitize_token(terminal).as_str(),
                            };
                            if tok.starts_with("Token::") {
                                code.push_str(&format!("            {} => {{\n", tok));
                            } else {
                                code.push_str(&format!("            \"{}\" => {{\n", tok));
                            }
                            code.push_str("                let mut children = Vec::new();\n");
                            for symbol in body {
                                if self.grammar.non_terminals.contains(symbol) {
                                    let sub_func = sanitize_func(symbol);
                                    code.push_str(&format!("                children.push(self.{}()?);\n", sub_func));
                                } else {
                                    match symbol.as_str() {
                                        "+" => {
                                            code.push_str("                self.eat(Token::PLUS)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::PLUS.clone()));\n");
                                        }
                                        "-" => {
                                            code.push_str("                self.eat(Token::MINUS)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::MINUS.clone()));\n");
                                        }
                                        "*" => {
                                            code.push_str("                self.eat(Token::STAR)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::STAR.clone()));\n");
                                        }
                                        "/" => {
                                            code.push_str("                self.eat(Token::SLASH)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::SLASH.clone()));\n");
                                        }
                                        "(" => {
                                            code.push_str("                self.eat(Token::L_PAREN)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::L_PAREN.clone()));\n");
                                        }
                                        ")" => {
                                            code.push_str("                self.eat(Token::R_PAREN)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::R_PAREN.clone()));\n");
                                        }
                                        "id" => {
                                            code.push_str("                if let Token::ID(value) = &self.current_token {\n");
                                            code.push_str("                    self.eat(Token::ID(value.clone()))?;\n");
                                            code.push_str("                    children.push(ASTNode::Identifier(value.clone()));\n");
                                            code.push_str("                } else {\n");
                                            code.push_str("                    return Err(ParseError::UnexpectedToken {\n");
                                            code.push_str("                        expected: vec![\"id\".to_string()],\n");
                                            code.push_str("                        found: format!(\"{:?}\", self.current_token),\n");
                                            code.push_str("                        position: self.position,\n");
                                            code.push_str("                    });\n");
                                            code.push_str("                }\n");
                                        }
                                        "number" => {
                                            code.push_str("                if let Token::NUMBER(value) = self.current_token.clone() {\n");
                                            code.push_str("                    self.eat(Token::NUMBER(value))?;\n");
                                            code.push_str("                    children.push(ASTNode::Number(value));\n");
                                            code.push_str("                } else {\n");
                                            code.push_str("                    return Err(ParseError::UnexpectedToken {\n");
                                            code.push_str("                        expected: vec![\"number\".to_string()],\n");
                                            code.push_str("                        found: format!(\"{:?}\", self.current_token),\n");
                                            code.push_str("                        position: self.position,\n");
                                            code.push_str("                    });\n");
                                            code.push_str("                }\n");
                                        }
                                        _ => {
                                            code.push_str(&format!("                // Unknown terminal '{}'\n", symbol));
                                        }
                                    }
                                }
                            }
                            code.push_str(&format!(
                                "                Ok(ASTNode::NonTerminal(\"{}\".to_string()))\n",
                                rule.head
                            ));
                            code.push_str("            },\n");
                        }
                    }

                    // Handle ε-productions
                    if first_set.contains("ε") {
                        let follow_set = &self.follow_sets[&rule.head];
                        for terminal in follow_set {
                            let tok = match terminal.as_str() {
                                "$" => "Token::EOF",
                                "+" => "Token::PLUS",
                                "-" => "Token::MINUS",
                                "*" => "Token::STAR",
                                "/" => "Token::SLASH",
                                "(" => "Token::L_PAREN",
                                ")" => "Token::R_PAREN",
                                _ => sanitize_token(terminal).as_str(),
                            };
                            code.push_str(&format!("            {} => {{\n", tok));
                            code.push_str(&format!(
                                "                // ε-production for '{}'\n",
                                rule.head
                            ));
                            code.push_str(&format!(
                                "                Ok(ASTNode::NonTerminal(\"{}\".to_string()))\n",
                                rule.head
                            ));
                            code.push_str("            },\n");
                        }
                    }
                }

                // Error case
                code.push_str("            _ => Err(ParseError::UnexpectedToken {\n");
                code.push_str("                expected: vec![\"expected tokens based on grammar\".to_string()],\n");
                code.push_str("                found: format!(\"{:?}\", self.current_token),\n");
                code.push_str("                position: self.position,\n");
                code.push_str("            }),\n");
                code.push_str("        }\n");
                code.push_str("    }\n\n");
            }

            // Implement parse AST function
            code.push_str("    /// Initiates the parsing process and returns the AST.\n");
            code.push_str("    pub fn parse_ast(&mut self) -> Result<ASTNode, ParseError> {\n");
            code.push_str("        self.parse()\n");
            code.push_str("    }\n");
            code.push_str("}\n\n");

            // Lexer implementation (same as above)
            code.push_str("#[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("pub enum Token {\n");
            for terminal in &self.grammar.terminals {
                if terminal == "id" {
                    code.push_str("    ID(String),\n");
                } else if terminal == "number" {
                    code.push_str("    NUMBER(i32),\n");
                } else {
                    let tok = sanitize_token(terminal);
                    code.push_str(&format!("    {},\n", tok));
                }
            }
            code.push_str("    EOF,\n");
            code.push_str("}\n\n");

            // Lexer struct and implementation
            code.push_str("use std::iter::Peekable;\n");
            code.push_str("use std::str::Chars;\n\n");
            code.push_str("struct Lexer {\n");
            code.push_str("    input: Peekable<Chars<'static>>,\n");
            code.push_str("    buffer: Vec<Token>,\n");
            code.push_str("    regex_map: Vec<(Regex, fn(&str) -> Token)>,\n");
            code.push_str("    current_position: usize,\n");
            code.push_str("}\n\n");
            code.push_str("impl Lexer {\n");
            code.push_str("    fn new(input: &str) -> Self {\n");
            code.push_str("        let input_owned = input.to_string();\n");
            code.push_str("        let input_static: &'static str = Box::leak(input_owned.into_boxed_str());\n");
            code.push_str("        let mut regex_map = Vec::new();\n");
            code.push_str("        // Order matters: longer patterns first\n");
            code.push_str("        regex_map.push((Regex::new(r\"^==\").unwrap(), |_| Token::EQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^!=\").unwrap(), |_| Token::NEQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^<=\").unwrap(), |_| Token::LEQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^>=\").unwrap(), |_| Token::GEQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\+\").unwrap(), |_| Token::PLUS));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^-\\\").unwrap(), |_| Token::MINUS));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\*\").unwrap(), |_| Token::STAR));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^/\").unwrap(), |_| Token::SLASH));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\(\").unwrap(), |_| Token::L_PAREN));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\)\").unwrap(), |_| Token::R_PAREN));\n");
            code.push_str("        // Identifiers\n");
            code.push_str("        regex_map.push((\n");
            code.push_str("            Regex::new(r\"^[a-zA-Z_][a-zA-Z0-9_]*\").unwrap(),\n");
            code.push_str("            |s| Token::ID(s.to_string()),\n");
            code.push_str("        ));\n");
            code.push_str("        // Numbers\n");
            code.push_str("        regex_map.push((\n");
            code.push_str("            Regex::new(r\"^\\d+\").unwrap(),\n");
            code.push_str("            |s| Token::NUMBER(s.parse().unwrap()),\n");
            code.push_str("        ));\n");
            code.push_str("\n");
            code.push_str("        Lexer {\n");
            code.push_str("            input: input_static.chars().peekable(),\n");
            code.push_str("            buffer: Vec::new(),\n");
            code.push_str("            regex_map,\n");
            code.push_str("            current_position: 0,\n");
            code.push_str("        }\n");
            code.push_str("    }\n\n");

            code.push_str("    fn next_token(&mut self) -> Token {\n");
            code.push_str("        if !self.buffer.is_empty() {\n");
            code.push_str("            return self.buffer.remove(0);\n");
            code.push_str("        }\n");
            code.push_str("        self.lex_next_token()\n");
            code.push_str("    }\n\n");

            code.push_str("    fn peek(&mut self, k: usize) -> Vec<Token> {\n");
            code.push_str("        while self.buffer.len() < k {\n");
            code.push_str("            let token = self.lex_next_token();\n");
            code.push_str("            if token == Token::EOF {\n");
            code.push_str("                break;\n");
            code.push_str("            }\n");
            code.push_str("            self.buffer.push(token);\n");
            code.push_str("        }\n");
            code.push_str("        self.buffer.iter().cloned().take(k).collect()\n");
            code.push_str("    }\n\n");

            code.push_str("    fn lex_next_token(&mut self) -> Token {\n");
            code.push_str("        let remaining: String = self.input.clone().collect();\n");
            code.push_str("        for (regex, constructor) in &self.regex_map {\n");
            code.push_str("            if let Some(mat) = regex.find(&remaining) {\n");
            code.push_str("                let matched_str = mat.as_str();\n");
            code.push_str("                let token = constructor(matched_str);\n");
            code.push_str("                // Advance the input by the length of the matched string\n");
            code.push_str("                for _ in 0..matched_str.len() {\n");
            code.push_str("                    self.input.next();\n");
            code.push_str("                    self.current_position += 1;\n");
            code.push_str("                }\n");
            code.push_str("                return token;\n");
            code.push_str("            }\n");
            code.push_str("        }\n\n");
            code.push_str("        // If no regex matched, handle unknown characters\n");
            code.push_str("        if let Some(c) = self.input.next() {\n");
            code.push_str("            self.current_position += 1;\n");
            code.push_str("            eprintln!(\"Warning: Unrecognized character '{}'\", c);\n");
            code.push_str("            Token::EOF\n");
            code.push_str("        } else {\n");
            code.push_str("            Token::EOF\n");
            code.push_str("        }\n");
            code.push_str("    }\n");
            code.push_str("}\n\n");

            // AST Node definitions
            code.push_str("/// Represents the Abstract Syntax Tree (AST).\n");
            code.push_str("#[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("pub enum ASTNode {\n");
            code.push_str("    NonTerminal(String),\n");
            code.push_str("    Terminal(Token),\n");
            code.push_str("    Identifier(String),\n");
            code.push_str("    Number(i32),\n");
            code.push_str("}\n\n");

            // Grammar struct
            code.push_str("/// Represents the entire parsed grammar.\n");
            code.push_str("#[derive(Debug, Clone)]\n");
            code.push_str("pub struct Grammar {\n");
            code.push_str("    pub rules: Vec<Rule>,\n");
            code.push_str("    pub terminals: HashSet<String>,\n");
            code.push_str("    pub non_terminals: HashSet<String>,\n");
            code.push_str("    pub first_sets: HashMap<String, HashSet<String>>, \n");
            code.push_str("    pub follow_sets: HashMap<String, HashSet<String>>, \n");
            code.push_str("}\n\n");

            // Code generation logic
            code.push_str("/// Generates Rust code for the parser based on the parsed grammar.\n");
            code.push_str("fn generate_rust_code(grammar: &Grammar, grammar_type: &str, lookahead: usize) -> String {\n");
            code.push_str("    let mut code = String::new();\n\n");

            // Header with documentation
            code.push_str("    // Generated by Thepg: A Rust-Based Parser Generator\n");
            code.push_str("    code.push_str(\"//! # Generated Parser\\n\");\n");
            code.push_str("    code.push_str(\"//!\\n\");\n");
            code.push_str("    code.push_str(\"//! This parser was automatically generated by **Thepg**, a Rust-based parser generator.\\n\");\n");
            code.push_str("    code.push_str(\"//! It is designed to parse inputs based on the provided ENBF grammar.\\n\");\n");
            code.push_str("    code.push_str(\"//!\\n\");\n");
            code.push_str("    code.push_str(\"//! ## Features\\n\");\n");
            code.push_str("    code.push_str(\"//! - Lexer-free parsing\\n\");\n");
            code.push_str("    code.push_str(\"//! - Supports LL(1) and LL(k) parsing strategies\\n\");\n");
            code.push_str("    code.push_str(\"//! - Constructs Abstract Syntax Trees (AST)\\n\");\n");
            code.push_str("    code.push_str(\"//!\\n\");\n");
            code.push_str("    code.push_str(\"//! ## Usage\\n\");\n");
            code.push_str("    code.push_str(\"//! ```rust\\n\");\n");
            code.push_str("    code.push_str(\"//! use crate::Parser;\\n\");\n");
            code.push_str("    code.push_str(\"//!\\n\");\n");
            code.push_str("    code.push_str(\"//! fn main() {\\n\");\n");
            code.push_str("    code.push_str(\"//!     let input = \\\"your_input_here\\\";\\n\");\n");
            code.push_str("    code.push_str(\"//!     let mut parser = Parser::new(input);\\n\");\n");
            code.push_str("    code.push_str(\"//!     match parser.parse_ast() {\\n\");\n");
            code.push_str("    code.push_str(\"//!         Ok(ast) => println!(\\\"Parsing succeeded. AST: {:?}\\\", ast),\\n\");\n");
            code.push_str("    code.push_str(\"//!         Err(e) => println!(\\\"Parsing failed: {}\\\", e),\\n\");\n");
            code.push_str("    code.push_str(\"//!     }\\n\");\n");
            code.push_str("    code.push_str(\"//! }\\n\");\n");
            code.push_str("    code.push_str(\"//! ```\\n\");\n");
            code.push_str("    code.push_str(\"//!\\n\");\n");

            // Token definitions
            code.push_str("    #[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("    pub enum Token {\n");
            for terminal in &grammar.terminals {
                if terminal == "id" {
                    code.push_str("        ID(String),\n");
                } else if terminal == "number" {
                    code.push_str("        NUMBER(i32),\n");
                } else {
                    let tok = sanitize_token(terminal);
                    code.push_str(&format!("        {},\n", tok));
                }
            }
            code.push_str("        EOF,\n");
            code.push_str("    }\n\n");

            // AST Node definitions
            code.push_str("    #[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("    pub enum ASTNode {\n");
            code.push_str("        NonTerminal(String),\n");
            code.push_str("        Terminal(Token),\n");
            code.push_str("        Identifier(String),\n");
            code.push_str("        Number(i32),\n");
            code.push_str("    }\n\n");

            // Parser struct definition
            code.push_str("    /// The Parser struct responsible for parsing input strings and constructing ASTs.\n");
            code.push_str("    pub struct Parser {\n");
            code.push_str("        lexer: Lexer,\n");
            code.push_str("        current_token: Token,\n");
            code.push_str("        grammar: &'static Grammar,\n");
            code.push_str("        lookahead: usize,\n");
            code.push_str("        position: usize,\n");
            code.push_str("    }\n\n");

            // Implement Parser
            code.push_str("    impl Parser {\n");
            code.push_str("        /// Creates a new Parser instance.\n");
            code.push_str("        ///\n");
            code.push_str("        /// # Arguments\n");
            code.push_str("        ///\n");
            code.push_str("        /// * `input` - The input string to be parsed.\n");
            code.push_str("        /// * `grammar` - A reference to the parsed Grammar struct.\n");
            code.push_str("        /// * `lookahead` - The number of tokens to look ahead during parsing.\n");
            code.push_str("        ///\n");
            code.push_str("        /// # Example\n");
            code.push_str("        ///\n");
            code.push_str("        /// ```rust\n");
            code.push_str("        /// let grammar = Grammar::parse(grammar_str).unwrap();\n");
            code.push_str("        /// let mut parser = Parser::new(\"id + id * id\", &grammar, 2);\n");
            code.push_str("        /// ```\n");
            code.push_str("        pub fn new(input: &str, grammar: &'static Grammar, lookahead: usize) -> Self {\n");
            code.push_str("            let mut lexer = Lexer::new(input);\n");
            code.push_str("            let first_token = lexer.next_token();\n");
            code.push_str("            Parser {\n");
            code.push_str("                lexer,\n");
            code.push_str("                current_token: first_token,\n");
            code.push_str("                grammar,\n");
            code.push_str("                lookahead,\n");
            code.push_str("                position: 0,\n");
            code.push_str("            }\n");
            code.push_str("        }\n\n");

            // Parsing functions generated based on grammar rules
            for rule in &self.grammar.rules {
                let func_name = sanitize_func(&rule.head);
                code.push_str(&format!("        /// Parses the `{}` non-terminal.\n", rule.head));
                code.push_str(&format!("        pub fn {}(&mut self) -> Result<ASTNode, ParseError> {{\n", func_name));
                code.push_str("            match &self.current_token {\n");

                for body in &rule.bodies {
                    let first_set = first_of_body(body, &self.grammar.first_sets).unwrap();
                    for terminal in &first_set {
                        if terminal != "ε" {
                            let tok = match terminal.as_str() {
                                "+" => "Token::PLUS",
                                "-" => "Token::MINUS",
                                "*" => "Token::STAR",
                                "/" => "Token::SLASH",
                                "(" => "Token::L_PAREN",
                                ")" => "Token::R_PAREN",
                                "id" => "Token::ID(_)".to_string(),
                                "number" => "Token::NUMBER(_)".to_string(),
                                _ => sanitize_token(terminal).as_str(),
                            };
                            if tok.starts_with("Token::") {
                                code.push_str(&format!("                {} => {{\n", tok));
                            } else {
                                code.push_str(&format!("                \"{}\" => {{\n", tok));
                            }
                            code.push_str("                    let mut children = Vec::new();\n");
                            for symbol in body {
                                if self.grammar.non_terminals.contains(symbol) {
                                    let sub_func = sanitize_func(symbol);
                                    code.push_str(&format!("                    children.push(self.{}()?);\n", sub_func));
                                } else {
                                    match symbol.as_str() {
                                        "+" => {
                                            code.push_str("                    self.eat(Token::PLUS)?;\n");
                                            code.push_str("                    children.push(ASTNode::Terminal(Token::PLUS.clone()));\n");
                                        }
                                        "-" => {
                                            code.push_str("                    self.eat(Token::MINUS)?;\n");
                                            code.push_str("                    children.push(ASTNode::Terminal(Token::MINUS.clone()));\n");
                                        }
                                        "*" => {
                                            code.push_str("                    self.eat(Token::STAR)?;\n");
                                            code.push_str("                    children.push(ASTNode::Terminal(Token::STAR.clone()));\n");
                                        }
                                        "/" => {
                                            code.push_str("                    self.eat(Token::SLASH)?;\n");
                                            code.push_str("                    children.push(ASTNode::Terminal(Token::SLASH.clone()));\n");
                                        }
                                        "(" => {
                                            code.push_str("                    self.eat(Token::L_PAREN)?;\n");
                                            code.push_str("                    children.push(ASTNode::Terminal(Token::L_PAREN.clone()));\n");
                                        }
                                        ")" => {
                                            code.push_str("                    self.eat(Token::R_PAREN)?;\n");
                                            code.push_str("                    children.push(ASTNode::Terminal(Token::R_PAREN.clone()));\n");
                                        }
                                        "id" => {
                                            code.push_str("                    if let Token::ID(value) = &self.current_token {\n");
                                            code.push_str("                        self.eat(Token::ID(value.clone()))?;\n");
                                            code.push_str("                        children.push(ASTNode::Identifier(value.clone()));\n");
                                            code.push_str("                    } else {\n");
                                            code.push_str("                        return Err(ParseError::UnexpectedToken {\n");
                                            code.push_str("                            expected: vec![\"id\".to_string()],\n");
                                            code.push_str("                            found: format!(\"{:?}\", self.current_token),\n");
                                            code.push_str("                            position: self.position,\n");
                                            code.push_str("                        });\n");
                                            code.push_str("                    }\n");
                                        }
                                        "number" => {
                                            code.push_str("                    if let Token::NUMBER(value) = self.current_token.clone() {\n");
                                            code.push_str("                        self.eat(Token::NUMBER(value))?;\n");
                                            code.push_str("                        children.push(ASTNode::Number(value));\n");
                                            code.push_str("                    } else {\n");
                                            code.push_str("                        return Err(ParseError::UnexpectedToken {\n");
                                            code.push_str("                            expected: vec![\"number\".to_string()],\n");
                                            code.push_str("                            found: format!(\"{:?}\", self.current_token),\n");
                                            code.push_str("                            position: self.position,\n");
                                            code.push_str("                        });\n");
                                            code.push_str("                    }\n");
                                        }
                                        _ => {
                                            code.push_str(&format!("                    // Unknown terminal '{}'\n", symbol));
                                        }
                                    }
                                }
                            }
                            code.push_str(&format!(
                                "                    Ok(ASTNode::NonTerminal(\"{}\".to_string()))\n",
                                rule.head
                            ));
                            code.push_str("                },\n");
                        }
                    }

                    // Handle ε-productions
                    if first_set.contains("ε") {
                        let follow_set = &self.follow_sets[&rule.head];
                        for terminal in follow_set {
                            let tok = match terminal.as_str() {
                                "$" => "Token::EOF",
                                "+" => "Token::PLUS",
                                "-" => "Token::MINUS",
                                "*" => "Token::STAR",
                                "/" => "Token::SLASH",
                                "(" => "Token::L_PAREN",
                                ")" => "Token::R_PAREN",
                                _ => sanitize_token(terminal).as_str(),
                            };
                            code.push_str(&format!("                {} => {{\n", tok));
                            code.push_str(&format!(
                                "                    // ε-production for '{}'\n",
                                rule.head
                            ));
                            code.push_str(&format!(
                                "                    Ok(ASTNode::NonTerminal(\"{}\".to_string()))\n",
                                rule.head
                            ));
                            code.push_str("                },\n");
                        }
                    }
                }

                // Error case
                code.push_str("                _ => Err(ParseError::UnexpectedToken {\n");
                code.push_str("                    expected: vec![\"expected tokens based on grammar\".to_string()],\n");
                code.push_str("                    found: format!(\"{:?}\", self.current_token),\n");
                code.push_str("                    position: self.position,\n");
                code.push_str("                }),\n");
                code.push_str("            }\n");
                code.push_str("        }\n");
                code.push_str("    }\n\n");
            }

            // Implement parsing functions based on grammar rules
            for rule in &self.grammar.rules {
                let func_name = sanitize_func(&rule.head);
                code.push_str(&format!(
                    "    /// Parses the `{}` non-terminal and constructs the corresponding AST node.\n",
                    rule.head
                ));
                code.push_str(&format!(
                    "    fn {}(&mut self) -> Result<ASTNode, ParseError> {{\n",
                    func_name
                ));
                code.push_str("        match &self.current_token {\n");

                for body in &rule.bodies {
                    let first_set = first_of_body(body, &self.grammar.first_sets).unwrap();
                    for terminal in &first_set {
                        if terminal != "ε" {
                            let tok = match terminal.as_str() {
                                "+" => "Token::PLUS",
                                "-" => "Token::MINUS",
                                "*" => "Token::STAR",
                                "/" => "Token::SLASH",
                                "(" => "Token::L_PAREN",
                                ")" => "Token::R_PAREN",
                                "id" => "Token::ID(_)".to_string(),
                                "number" => "Token::NUMBER(_)".to_string(),
                                _ => sanitize_token(terminal).as_str(),
                            };
                            if tok.starts_with("Token::") {
                                code.push_str(&format!("            {} => {{\n", tok));
                            } else {
                                code.push_str(&format!("            \"{}\" => {{\n", tok));
                            }
                            code.push_str("                let mut children = Vec::new();\n");
                            for symbol in body {
                                if self.grammar.non_terminals.contains(symbol) {
                                    let sub_func = sanitize_func(symbol);
                                    code.push_str(&format!("                children.push(self.{}()?);\n", sub_func));
                                } else {
                                    match symbol.as_str() {
                                        "+" => {
                                            code.push_str("                self.eat(Token::PLUS)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::PLUS.clone()));\n");
                                        }
                                        "-" => {
                                            code.push_str("                self.eat(Token::MINUS)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::MINUS.clone()));\n");
                                        }
                                        "*" => {
                                            code.push_str("                self.eat(Token::STAR)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::STAR.clone()));\n");
                                        }
                                        "/" => {
                                            code.push_str("                self.eat(Token::SLASH)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::SLASH.clone()));\n");
                                        }
                                        "(" => {
                                            code.push_str("                self.eat(Token::L_PAREN)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::L_PAREN.clone()));\n");
                                        }
                                        ")" => {
                                            code.push_str("                self.eat(Token::R_PAREN)?;\n");
                                            code.push_str("                children.push(ASTNode::Terminal(Token::R_PAREN.clone()));\n");
                                        }
                                        "id" => {
                                            code.push_str("                if let Token::ID(value) = &self.current_token {\n");
                                            code.push_str("                    self.eat(Token::ID(value.clone()))?;\n");
                                            code.push_str("                    children.push(ASTNode::Identifier(value.clone()));\n");
                                            code.push_str("                } else {\n");
                                            code.push_str("                    return Err(ParseError::UnexpectedToken {\n");
                                            code.push_str("                        expected: vec![\"id\".to_string()],\n");
                                            code.push_str("                        found: format!(\"{:?}\", self.current_token),\n");
                                            code.push_str("                        position: self.position,\n");
                                            code.push_str("                    });\n");
                                            code.push_str("                }\n");
                                        }
                                        "number" => {
                                            code.push_str("                if let Token::NUMBER(value) = self.current_token.clone() {\n");
                                            code.push_str("                    self.eat(Token::NUMBER(value))?;\n");
                                            code.push_str("                    children.push(ASTNode::Number(value));\n");
                                            code.push_str("                } else {\n");
                                            code.push_str("                    return Err(ParseError::UnexpectedToken {\n");
                                            code.push_str("                        expected: vec![\"number\".to_string()],\n");
                                            code.push_str("                        found: format!(\"{:?}\", self.current_token),\n");
                                            code.push_str("                        position: self.position,\n");
                                            code.push_str("                    });\n");
                                            code.push_str("                }\n");
                                        }
                                        _ => {
                                            code.push_str(&format!("                // Unknown terminal '{}'\n", symbol));
                                        }
                                    }
                                }
                            }
                            code.push_str(&format!(
                                "                Ok(ASTNode::NonTerminal(\"{}\".to_string()))\n",
                                rule.head
                            ));
                            code.push_str("            },\n");
                        }
                    }

                    // Handle ε-productions
                    if first_set.contains("ε") {
                        let follow_set = &self.follow_sets[&rule.head];
                        for terminal in follow_set {
                            let tok = match terminal.as_str() {
                                "$" => "Token::EOF",
                                "+" => "Token::PLUS",
                                "-" => "Token::MINUS",
                                "*" => "Token::STAR",
                                "/" => "Token::SLASH",
                                "(" => "Token::L_PAREN",
                                ")" => "Token::R_PAREN",
                                _ => sanitize_token(terminal).as_str(),
                            };
                            code.push_str(&format!("            {} => {{\n", tok));
                            code.push_str(&format!(
                                "                // ε-production for '{}'\n",
                                rule.head
                            ));
                            code.push_str(&format!(
                                "                Ok(ASTNode::NonTerminal(\"{}\".to_string()))\n",
                                rule.head
                            ));
                            code.push_str("            },\n");
                        }
                    }
                }

                // Error case
                code.push_str("            _ => Err(ParseError::UnexpectedToken {\n");
                code.push_str("                expected: vec![\"expected tokens based on grammar\".to_string()],\n");
                code.push_str("                found: format!(\"{:?}\", self.current_token),\n");
                code.push_str("                position: self.position,\n");
                code.push_str("            }),\n");
                code.push_str("        }\n");
                code.push_str("    }\n\n");
            }

            // Implement parse AST function
            code.push_str("    /// Initiates the parsing process and returns the AST.\n");
            code.push_str("    pub fn parse_ast(&mut self) -> Result<ASTNode, ParseError> {\n");
            code.push_str("        self.parse()\n");
            code.push_str("    }\n");
            code.push_str("}\n\n");

            // Implement the GENERATED Lexer (for completeness, assuming it's part of the generated code)
            code.push_str("/// The Lexer struct responsible for tokenizing the input string.\n");
            code.push_str("#[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("pub struct Lexer {\n");
            code.push_str("    input: Peekable<Chars<'static>>,\n");
            code.push_str("    buffer: Vec<Token>,\n");
            code.push_str("    regex_map: Vec<(Regex, fn(&str) -> Token)>,\n");
            code.push_str("    current_position: usize,\n");
            code.push_str("}\n\n");
            code.push_str("impl Lexer {\n");
            code.push_str("    /// Creates a new Lexer instance.\n");
            code.push_str("    pub fn new(input: &'static str) -> Self {\n");
            code.push_str("        let mut regex_map = Vec::new();\n");
            code.push_str("        // Order matters: longer patterns first\n");
            code.push_str("        regex_map.push((Regex::new(r\"^==\").unwrap(), |_| Token::EQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^!=\").unwrap(), |_| Token::NEQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^<=\").unwrap(), |_| Token::LEQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^>=\").unwrap(), |_| Token::GEQ));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\+\").unwrap(), |_| Token::PLUS));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^-\").unwrap(), |_| Token::MINUS));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\*\").unwrap(), |_| Token::STAR));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^/\").unwrap(), |_| Token::SLASH));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\(\").unwrap(), |_| Token::L_PAREN));\n");
            code.push_str("        regex_map.push((Regex::new(r\"^\\)\").unwrap(), |_| Token::R_PAREN));\n");
            code.push_str("        // Identifiers\n");
            code.push_str("        regex_map.push((\n");
            code.push_str("            Regex::new(r\"^[a-zA-Z_][a-zA-Z0-9_]*\").unwrap(),\n");
            code.push_str("            |s| Token::ID(s.to_string()),\n");
            code.push_str("        ));\n");
            code.push_str("        // Numbers\n");
            code.push_str("        regex_map.push((\n");
            code.push_str("            Regex::new(r\"^\\d+\").unwrap(),\n");
            code.push_str("            |s| Token::NUMBER(s.parse().unwrap()),\n");
            code.push_str("        ));\n");
            code.push_str("\n");
            code.push_str("        Lexer {\n");
            code.push_str("            input: input.chars().peekable(),\n");
            code.push_str("            buffer: Vec::new(),\n");
            code.push_str("            regex_map,\n");
            code.push_str("            current_position: 0,\n");
            code.push_str("        }\n");
            code.push_str("    }\n\n");

            code.push_str("    /// Retrieves the next token from the buffer or lexer.\n");
            code.push_str("    pub fn next_token(&mut self) -> Token {\n");
            code.push_str("        if !self.buffer.is_empty() {\n");
            code.push_str("            return self.buffer.remove(0);\n");
            code.push_str("        }\n");
            code.push_str("        self.lex_next_token()\n");
            code.push_str("    }\n\n");

            code.push_str("    /// Peeks `k` tokens ahead without consuming them.\n");
            code.push_str("    pub fn peek(&mut self, k: usize) -> Vec<Token> {\n");
            code.push_str("        while self.buffer.len() < k {\n");
            code.push_str("            let token = self.lex_next_token();\n");
            code.push_str("            if token == Token::EOF {\n");
            code.push_str("                break;\n");
            code.push_str("            }\n");
            code.push_str("            self.buffer.push(token);\n");
            code.push_str("        }\n");
            code.push_str("        self.buffer.iter().cloned().take(k).collect()\n");
            code.push_str("    }\n\n");

            code.push_str("    /// Lexes the next token using regex patterns.\n");
            code.push_str("    fn lex_next_token(&mut self) -> Token {\n");
            code.push_str("        let remaining: String = self.input.clone().collect();\n");
            code.push_str("        for (regex, constructor) in &self.regex_map {\n");
            code.push_str("            if let Some(mat) = regex.find(&remaining) {\n");
            code.push_str("                let matched_str = mat.as_str();\n");
            code.push_str("                let token = constructor(matched_str);\n");
            code.push_str("                // Advance the input by the length of the matched string\n");
            code.push_str("                for _ in 0..matched_str.len() {\n");
            code.push_str("                    self.input.next();\n");
            code.push_str("                    self.current_position += 1;\n");
            code.push_str("                }\n");
            code.push_str("                return token;\n");
            code.push_str("            }\n");
            code.push_str("        }\n\n");
            code.push_str("        // If no regex matched, handle unknown characters\n");
            code.push_str("        if let Some(c) = self.input.next() {\n");
            code.push_str("            self.current_position += 1;\n");
            code.push_str("            eprintln!(\"Warning: Unrecognized character '{}'\", c);\n");
            code.push_str("            Token::EOF\n");
            code.push_str("        } else {\n");
            code.push_str("            Token::EOF\n");
            code.push_str("        }\n");
            code.push_str("    }\n");
            code.push_str("}\n\n");

            // Generate the AST, Lexer, Grammar, and Parser within the generated code
            code.push_str("/// Represents the Abstract Syntax Tree (AST).\n");
            code.push_str("#[derive(Debug, PartialEq, Clone)]\n");
            code.push_str("pub enum ASTNode {\n");
            code.push_str("    NonTerminal(String),\n");
            code.push_str("    Terminal(Token),\n");
            code.push_str("    Identifier(String),\n");
            code.push_str("    Number(i32),\n");
            code.push_str("}\n\n");

            // You can add more sophisticated AST node constructors here based on the grammar

            // Return the generated code
            code
        }
    }

    /// Entry point for Thepg
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        // Define the CLI using clap
        let matches = Command::new("Thepg")
            .version("1.0")
            .author("Your Name <youremail@example.com>")
            .about("A Rust-Based Parser Generator for ENBF Grammars")
            .arg(
                Arg::new("input")
                    .short('i')
                    .long("input")
                    .value_name("FILE")
                    .help("Input ENBF grammar file")
                    .required(true)
                    .takes_value(true),
            )
            .arg(
                Arg::new("output")
                    .short('o')
                    .long("output")
                    .value_name("FILE")
                    .help("Output Rust file for the generated parser")
                    .required(true)
                    .takes_value(true),
            )
            .arg(
                Arg::new("grammar_type")
                    .short('g')
                    .long("grammar-type")
                    .value_name("TYPE")
                    .help("Grammar type: LL1 or LLk")
                    .required(true)
                    .takes_value(true),
            )
            .arg(
                Arg::new("lookahead")
                    .short('k')
                    .long("lookahead")
                    .value_name("K")
                    .help("Number of tokens to look ahead (applicable for LLk)")
                    .default_value("1")
                    .takes_value(true),
            )
            .arg(
                Arg::new("verbose")
                    .short('v')
                    .long("verbose")
                    .help("Enable verbose output")
                    .action(ArgAction::SetTrue),
            )
            .get_matches();

        // Extract arguments
        let input_file = matches
            .get_one::<String>("input")
            .expect("Input file is required");
        let output_file = matches
            .get_one::<String>("output")
            .expect("Output file is required");
        let grammar_type = matches
            .get_one::<String>("grammar_type")
            .expect("Grammar type is required");
        let lookahead: usize = matches
            .get_one::<String>("lookahead")
            .unwrap()
            .parse()
            .unwrap_or(1);
        let verbose = matches.get_flag("verbose");

        if verbose {
            println!("Input File: {}", input_file);
            println!("Output File: {}", output_file);
            println!("Grammar Type: {}", grammar_type);
            println!("Lookahead Size: {}", lookahead);
        }

        // Read the ENBF grammar file
        let enbf = fs::read_to_string(input_file)
            .map_err(|e| ParseError::InvalidGrammar(format!("Failed to read input file: {}", e)))?;

        // Parse the grammar
        let mut grammar = Grammar::parse(&enbf)?;
        if verbose {
            println!("Grammar parsed successfully.");
        }

        // Check if the grammar is LL(1) if specified
        if grammar_type.to_uppercase() == "LL1" {
            if !grammar.compute_first_sets().is_ok() || !grammar.compute_follow_sets().is_ok()
            {
                return Err(Box::new(ParseError::InvalidGrammar(
                    "Failed to compute FIRST/FOLLOW sets.".to_string(),
                )));
            }
            if let Err(_) = grammar.compute_follow_sets() {
                return Err(Box::new(ParseError::InvalidGrammar(
                    "Failed to compute FOLLOW sets.".to_string(),
                )));
            }
            let is_ll1 = grammar.is_ll1().unwrap_or(false);
            if !is_ll1 {
                return Err(Box::new(ParseError::InvalidGrammar(
                    "The provided grammar is not LL(1).".to_string(),
                )));
            }
            if verbose {
                println!("Grammar is confirmed to be LL(1).");
            }
        }

        // Generate Rust code for the parser
        let code_generator = CodeGenerator::new(&grammar, grammar_type, lookahead);
        let generated_code = code_generator.generate_rust_code(&grammar, grammar_type, lookahead);

        // Write the generated code to the output file
        fs::write(output_file, generated_code)
            .map_err(|e| ParseError::InvalidGrammar(format!("Failed to write output file: {}", e)))?;

        if verbose {
            println!("Parser generated successfully at '{}'.", output_file);
        }

        Ok(())
    }

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

        #[test]
        fn test_sanitize_token() {
            assert_eq!(sanitize_token("+"), "PLUS");
            assert_eq!(sanitize_token("-"), "MINUS");
            assert_eq!(sanitize_token("*"), "STAR");
            assert_eq!(sanitize_token("/"), "SLASH");
            assert_eq!(sanitize_token("("), "L_PAREN");
            assert_eq!(sanitize_token(")"), "R_PAREN");
            assert_eq!(sanitize_token("id"), "ID");
            assert_eq!(sanitize_token("number"), "NUMBER");
            assert_eq!(sanitize_token("!="), "EXCLAMATION");
            assert_eq!(sanitize_token(">="), "GEQ");
            assert_eq!(sanitize_token("<="), "LEQ");
        }

        #[test]
        fn test_sanitize_func() {
            assert_eq!(sanitize_func("Expr"), "expr");
            assert_eq!(sanitize_func("ExprPrime"), "exprprime");
            assert_eq!(sanitize_func("Term"), "term");
            assert_eq!(sanitize_func("TermPrime"), "termprime");
            assert_eq!(sanitize_func("Factor"), "factor");
        }

        #[test]
        fn test_first_of_body() {
            let mut first_sets = HashMap::new();
            first_sets.insert("Term".to_string(), vec!["id".to_string(), "number".to_string()].into_iter().collect());
            first_sets.insert("ExprPrime".to_string(), vec!["+".to_string(), "-".to_string(), "ε".to_string()].into_iter().collect());

            let body = vec!["Term".to_string(), "ExprPrime".to_string()];
            let first = first_of_body(&body, &first_sets).unwrap();
            assert!(first.contains("id"));
            assert!(first.contains("number"));
        }

        #[test]
        fn test_body_can_produce_epsilon() {
            let mut first_sets = HashMap::new();
            first_sets.insert("A".to_string(), vec!["ε".to_string()].into_iter().collect());
            first_sets.insert("B".to_string(), vec!["ε".to_string()].into_iter().collect());

            let body = vec!["A".to_string(), "B".to_string()];
            assert!(body_can_produce_epsilon(&body, &first_sets));
        }

        #[test]
        fn test_parse_grammar() {
            let enbf = r#"
                Expr ::= Term ExprPrime
                ExprPrime ::= "+" Term ExprPrime | "-" Term ExprPrime | ε
                Term ::= Factor TermPrime
                TermPrime ::= "*" Factor TermPrime | "/" Factor TermPrime | ε
                Factor ::= "(" Expr ")" | "id" | "number"
            "#;
            let grammar = Grammar::parse(enbf).expect("Failed to parse grammar");
            assert_eq!(grammar.rules.len(), 5);
            assert!(grammar.terminals.contains("+"));
            assert!(grammar.terminals.contains("-"));
            assert!(grammar.non_terminals.contains("Expr"));
            assert!(grammar.first_sets.contains_key("Expr"));
            assert!(grammar.follow_sets.contains_key("Expr"));
        }

        #[test]
        fn test_parser_valid_input() {
            let enbf = r#"
                Expr ::= Term ExprPrime
                ExprPrime ::= "+" Term ExprPrime | "-" Term ExprPrime | ε
                Term ::= Factor TermPrime
                TermPrime ::= "*" Factor TermPrime | "/" Factor TermPrime | ε
                Factor ::= "(" Expr ")" | "id" | "number"
            "#;
            let mut grammar = Grammar::parse(enbf).expect("Failed to parse grammar");
            grammar.compute_first_sets().expect("Failed to compute FIRST sets");
            grammar.compute_follow_sets().expect("Failed to compute FOLLOW sets");
            let input = "id + id * id";
            let mut parser = ParserStruct::new(input, &grammar, 2);
            let ast = parser.parse().expect("Parser failed on valid input");
            assert!(matches!(ast, ASTNode::NonTerminal(_)));
        }

        #[test]
        fn test_parser_invalid_input() {
            let enbf = r#"
                Expr ::= Term ExprPrime
                ExprPrime ::= "+" Term ExprPrime | "-" Term ExprPrime | ε
                Term ::= Factor TermPrime
                TermPrime ::= "*" Factor TermPrime | "/" Factor TermPrime | ε
                Factor ::= "(" Expr ")" | "id" | "number"
            "#;
            let mut grammar = Grammar::parse(enbf).expect("Failed to parse grammar");
            grammar.compute_first_sets().expect("Failed to compute FIRST sets");
            grammar.compute_follow_sets().expect("Failed to compute FOLLOW sets");
            let input = "id + * id";
            let mut parser = ParserStruct::new(input, &grammar, 2);
            let result = parser.parse();
            assert!(matches!(result, Err(ParseError::UnexpectedToken { .. })));
        }

        #[test]
        fn test_empty_input() {
            let enbf = r#"
                Expr ::= Term
                Term ::= "id" | "number"
            "#;
            let mut grammar = Grammar::parse(enbf).expect("Failed to parse grammar");
            grammar.compute_first_sets().expect("Failed to compute FIRST sets");
            grammar.compute_follow_sets().expect("Failed to compute FOLLOW sets");
            let input = "";
            let mut parser = ParserStruct::new(input, &grammar, 1);
            let result = parser.parse();
            assert!(matches!(result, Err(ParseError::UnexpectedToken { .. })));
        }
    }
}

fix compilation, currently:
Compiling playground v0.0.1 (/playground)
error: enum is not supported in `trait`s or `impl`s
   --> src/lib.rs:413:5
    |
413 |     enum TokenEnum {
    |     ^^^^^^^^^^^^^^
    |
    = help: consider moving the enum out to a nearby module scope

error: struct is not supported in `trait`s or `impl`s
   --> src/lib.rs:433:5
    |
433 |     struct Lexer {
    |     ^^^^^^^^^^^^
    |
    = help: consider moving the struct out to a nearby module scope

error: implementation is not supported in `trait`s or `impl`s
   --> src/lib.rs:440:5
    |
440 |     impl Lexer {
    |     ^^^^^^^^^^
    |
    = help: consider moving the implementation out to a nearby module scope

error: enum is not supported in `trait`s or `impl`s
   --> src/lib.rs:556:5
    |
556 |     enum ASTNode {
    |     ^^^^^^^^^^^^
    |
    = help: consider moving the enum out to a nearby module scope

error: struct is not supported in `trait`s or `impl`s
   --> src/lib.rs:564:5
    |
564 |     struct ParserStruct<'a> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider moving the struct out to a nearby module scope

error: implementation is not supported in `trait`s or `impl`s
   --> src/lib.rs:573:5
    |
573 |     impl<'a> ParserStruct<'a> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider moving the implementation out to a nearby module scope

error: struct is not supported in `trait`s or `impl`s
   --> src/lib.rs:825:5
    |
825 |     struct CodeGenerator {
    |     ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider moving the struct out to a nearby module scope

error: implementation is not supported in `trait`s or `impl`s
   --> src/lib.rs:831:5
    |
831 |     impl CodeGenerator {
    |     ^^^^^^^^^^^^^^^^^^
    |
    = help: consider moving the implementation out to a nearby module scope

error: module is not supported in `trait`s or `impl`s
    --> src/lib.rs:1811:5
     |
1811 |     mod tests {
     |     ^^^^^^^^^
     |
     = help: consider moving the module out to a nearby module scope

warning: unused import: `regex::Regex`
  --> src/lib.rs:59:5
   |
59 | use regex::Regex;
   |     ^^^^^^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default

warning: unused import: `std::env`
  --> src/lib.rs:61:5
   |
61 | use std::env;
   |     ^^^^^^^^

warning: unused import: `self`
  --> src/lib.rs:63:15
   |
63 | use std::io::{self, Write};
   |               ^^^^

warning: unused import: `std::path::Path`
  --> src/lib.rs:64:5
   |
64 | use std::path::Path;
   |     ^^^^^^^^^^^^^^^

error[E0277]: can't compare `&std::string::String` with `std::string::String`
   --> src/lib.rs:279:37
    |
279 |                         if &body[i] == nt {
    |                                     ^^ no implementation for `&std::string::String == std::string::String`
    |
    = help: the trait `PartialEq<std::string::String>` is not implemented for `&std::string::String`
help: consider removing the borrow
    |
279 -                         if &body[i] == nt {
279 +                         if body[i] == nt {
    |

error[E0599]: no method named `takes_value` found for struct `Arg` in the current scope
    --> src/lib.rs:1699:22
     |
1693 | /                 Arg::new("input")
1694 | |                     .short('i')
1695 | |                     .long("input")
1696 | |                     .value_name("FILE")
1697 | |                     .help("Input ENBF grammar file")
1698 | |                     .required(true)
1699 | |                     .takes_value(true),
     | |                     -^^^^^^^^^^^ method not found in `Arg`
     | |_____________________|
     |

error[E0599]: no method named `takes_value` found for struct `Arg` in the current scope
    --> src/lib.rs:1708:22
     |
1702 | /                 Arg::new("output")
1703 | |                     .short('o')
1704 | |                     .long("output")
1705 | |                     .value_name("FILE")
1706 | |                     .help("Output Rust file for the generated parser")
1707 | |                     .required(true)
1708 | |                     .takes_value(true),
     | |                     -^^^^^^^^^^^ method not found in `Arg`
     | |_____________________|
     |

error[E0599]: no method named `takes_value` found for struct `Arg` in the current scope
    --> src/lib.rs:1717:22
     |
1711 | /                 Arg::new("grammar_type")
1712 | |                     .short('g')
1713 | |                     .long("grammar-type")
1714 | |                     .value_name("TYPE")
1715 | |                     .help("Grammar type: LL1 or LLk")
1716 | |                     .required(true)
1717 | |                     .takes_value(true),
     | |                     -^^^^^^^^^^^ method not found in `Arg`
     | |_____________________|
     |

error[E0599]: no method named `takes_value` found for struct `Arg` in the current scope
    --> src/lib.rs:1726:22
     |
1720 | /                 Arg::new("lookahead")
1721 | |                     .short('k')
1722 | |                     .long("lookahead")
1723 | |                     .value_name("K")
1724 | |                     .help("Number of tokens to look ahead (applicable for LLk)")
1725 | |                     .default_value("1")
1726 | |                     .takes_value(true),
     | |                     -^^^^^^^^^^^ method not found in `Arg`
     | |_____________________|
     |

error[E0599]: no method named `is_ll1` found for struct `Grammar` in the current scope
    --> src/lib.rs:1784:34
     |
108  | struct Grammar {
     | -------------- method `is_ll1` not found for this struct
...
1784 |             let is_ll1 = grammar.is_ll1().unwrap_or(false);
     |                                  ^^^^^^ method not found in `Grammar`

error[E0433]: failed to resolve: use of undeclared type `CodeGenerator`
    --> src/lib.rs:1796:30
     |
1796 |         let code_generator = CodeGenerator::new(&grammar, grammar_type, lookahead);
     |                              ^^^^^^^^^^^^^ use of undeclared type `CodeGenerator`

warning: unused import: `Write`
  --> src/lib.rs:63:21
   |
63 | use std::io::{self, Write};
   |                     ^^^^^

error[E0507]: cannot move out of a shared reference
   --> src/lib.rs:203:73
    |
203 | ...                   nt_first.extend(symbol_first.iter().filter(|&&s| s != "ε").cloned());
    |                                                                   ^^-
    |                                                                     |
    |                                                                     data moved here
    |                                                                     move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
    |
help: consider removing the borrow
    |
203 -                             nt_first.extend(symbol_first.iter().filter(|&&s| s != "ε").cloned());
203 +                             nt_first.extend(symbol_first.iter().filter(|&s| s != "ε").cloned());
    |

error[E0507]: cannot move out of a shared reference
   --> src/lib.rs:344:55
    |
344 |                 first.extend(sym_first.iter().filter(|&&s| s != "ε").cloned());
    |                                                       ^^-
    |                                                         |
    |                                                         data moved here
    |                                                         move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
    |
help: consider removing the borrow
    |
344 -                 first.extend(sym_first.iter().filter(|&&s| s != "ε").cloned());
344 +                 first.extend(sym_first.iter().filter(|&s| s != "ε").cloned());
    |