rustcc 0.1.1

An little C Complier( now it's just WIP :) )
use std::env;
use std::process;
mod scanner;
mod ast;
mod parser;
mod interpreter;
mod precedence_parser;
mod codegen;

use scanner::Scanner;
use parser::Parser;
use interpreter::Interpreter;
use precedence_parser::PrecedenceParser;

// 打印用法信息
fn usage(prog: &str) {
    eprintln!("Usage: {} [--parser=type] [--mode=mode] infile", prog);
    eprintln!("  --parser=type    Specify parser type: 'precedence' (default) or 'recursive'");
    eprintln!("  --mode=mode      Specify execution mode: 'interpret' (default) or 'compile'");
    process::exit(1);
}

// 评估AST并打印结果
fn evaluate_and_print(ast: Box<ast::ASTNode>) {
    match Interpreter::evaluate(&ast) {
        Ok(result) => {
            println!("Result: {}", result);
        },
        Err(e) => {
            eprintln!("Evaluation error: {}", e);
            process::exit(1);
        },
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut parser_type = "precedence";
    let mut mode = "compile";
    let mut filename = "";

    // Parse command line arguments
    let mut remaining_args = args.len() - 1; // Subtract program name
    let mut arg_index = 1;

    while remaining_args > 0 {
        if args[arg_index].starts_with("--parser=") {
            parser_type = &args[arg_index][9..];
            arg_index += 1;
            remaining_args -= 1;
        } else if args[arg_index].starts_with("--mode=") {
            mode = &args[arg_index][7..];
            arg_index += 1;
            remaining_args -= 1;
        } else if filename.is_empty() {
            filename = &args[arg_index];
            arg_index += 1;
            remaining_args -= 1;
        } else {
            usage(&args[0]);
        }
    }

    if filename.is_empty() {
        usage(&args[0]);
    }

    if filename.is_empty() {
        usage(&args[0]);
    }
    match Scanner::new(filename) {
        Ok(scanner) => {
            match parser_type {
                "recursive" => {
                    match Parser::new(scanner) {
                        Ok(mut parser) => {
                            match parser.parse() {
                                Ok(ast) => {
                                    match mode {
                                        "interpret" => {
                                            evaluate_and_print(ast);
                                        },
                                        "compile" => {
                                            match codegen::CodeGenerator::new("out.s") {
                                                Ok(mut codegen) => {
                                                    if let Err(e) = codegen.generate_code(&ast) {
                                                        eprintln!("Code generation error: {}", e);
                                                        process::exit(1);
                                                    }
                                                    println!("Assembly code generated to out.s");

                                                    // Assemble the .s file into .o file using nasm
                                                    let assemble_output = std::process::Command::new("nasm")
                                                        .args(["-f", "win64", "out.s", "-o", "out.o"])
                                                        .output()
                                                        .expect("Failed to execute nasm");

                                                    if !assemble_output.status.success() {
                                                        eprintln!("Assembly failed");
                                                        eprintln!("stderr: {}", String::from_utf8_lossy(&assemble_output.stderr));
                                                        process::exit(1);
                                                    }

                                                    // Link the .o file into executable using gcc
                                                    let link_output = std::process::Command::new("gcc")
                                                        .args(["-o", "out.exe", "out.o"])
                                                        .output()
                                                        .expect("Failed to execute gcc");

                                                    if !link_output.status.success() {
                                                        eprintln!("Linking failed");
                                                        eprintln!("stderr: {}", String::from_utf8_lossy(&link_output.stderr));
                                                        process::exit(1);
                                                    }

                                                    println!("Executable file 'out.exe' generated successfully");

                                                    // Run the generated executable
                                                    let run_output = std::process::Command::new(".\\out.exe")
                                                        .output()
                                                        .expect("Failed to execute out.exe");

                                                    if !run_output.status.success() {
                                                        eprintln!("Execution failed");
                                                        eprintln!("stderr: {}", String::from_utf8_lossy(&run_output.stderr));
                                                        process::exit(1);
                                                    }

                                                    println!("Program output:");
                                                    println!("{}", String::from_utf8_lossy(&run_output.stdout));
                                                },
                                                Err(e) => {
                                                    eprintln!("Code generator initialization error: {}", e);
                                                    process::exit(1);
                                                },
                                            }
                                        },
                                        _ => {
                                            eprintln!("Invalid mode: {}", mode);
                                            usage(&args[0]);
                                        },
                                    }
                                },
                                Err(e) => {
                                    eprintln!("Parsing error: {}", e);
                                    process::exit(1);
                                },
                            }
                        },
                        Err(e) => {
                            eprintln!("Parser initialization error: {}", e);
                            process::exit(1);
                        },
                    }
                },
                "precedence" => {
                    match PrecedenceParser::new(scanner) {
                        Ok(mut parser) => {
                            match parser.parse() {
                                Ok(ast) => {
                                    match mode {
                                        "interpret" => {
                                            evaluate_and_print(ast);
                                        },
                                        "compile" => {
                                            match codegen::CodeGenerator::new("out.s") {
                                                Ok(mut codegen) => {
                                                    if let Err(e) = codegen.generate_code(&ast) {
                                                        eprintln!("Code generation error: {}", e);
                                                        process::exit(1);
                                                    }
                                                    println!("Assembly code generated to out.s");

                                                    // Assemble the .s file into .o file using nasm
                                                    let assemble_output = std::process::Command::new("nasm")
                                                        .args(["-f", "win64", "out.s", "-o", "out.o"])
                                                        .output()
                                                        .expect("Failed to execute nasm");

                                                    if !assemble_output.status.success() {
                                                        eprintln!("Assembly failed");
                                                        eprintln!("stderr: {}", String::from_utf8_lossy(&assemble_output.stderr));
                                                        process::exit(1);
                                                    }

                                                    // Link the .o file into executable using gcc
                                                    let link_output = std::process::Command::new("gcc")
                                                        .args(["-o", "out.exe", "out.o"])
                                                        .output()
                                                        .expect("Failed to execute gcc");

                                                    if !link_output.status.success() {
                                                        eprintln!("Linking failed");
                                                        eprintln!("stderr: {}", String::from_utf8_lossy(&link_output.stderr));
                                                        process::exit(1);
                                                    }

                                                    println!("Executable file 'out.exe' generated successfully");
                                                },
                                                Err(e) => {
                                                    eprintln!("Code generator initialization error: {}", e);
                                                    process::exit(1);
                                                },
                                            }
                                        },
                                        _ => {
                                            eprintln!("Invalid mode: {}", mode);
                                            usage(&args[0]);
                                        },
                                    }
                                },
                                Err(e) => {
                                    eprintln!("Parsing error: {}", e);
                                    process::exit(1);
                                },
                            }
                        },
                        Err(e) => {
                            eprintln!("Parser initialization error: {}", e);
                            process::exit(1);
                        },
                    }
                },
                _ => {
                    eprintln!("Unknown parser type: {}", parser_type);
                    usage(&args[0]);
                }
            }

        },
        Err(e) => {
            eprintln!("Unable to open {}: {}", filename, e);
            process::exit(1);
        },
    }
}