ripex 0.2.0

Multi-language structural parsing and fact extraction.
Documentation
use crate::arena::Arena;
use crate::js::ast::Program;

use super::printer::{GenerationError, Printer};

pub fn minify(source: &str, _program: &Program) -> String {
    let mut output = String::new();
    let mut in_string = false;
    let mut string_char = '"';
    let mut prev_char = ' ';

    let chars: Vec<char> = source.chars().collect();
    let mut i = 0;

    while i < chars.len() {
        let c = chars[i];

        if in_string {
            output.push(c);
            if c == '\\' && i + 1 < chars.len() {
                i += 1;
                output.push(chars[i]);
            } else if c == string_char {
                in_string = false;
            }
            i += 1;
            continue;
        }

        if c == '"' || c == '\'' || c == '`' {
            in_string = true;
            string_char = c;
            output.push(c);
            i += 1;
            continue;
        }

        if c == '/' && i + 1 < chars.len() {
            if chars[i + 1] == '/' {
                while i < chars.len() && chars[i] != '\n' {
                    i += 1;
                }
                continue;
            }
            if chars[i + 1] == '*' {
                i += 2;
                while i + 1 < chars.len() && !(chars[i] == '*' && chars[i + 1] == '/') {
                    i += 1;
                }
                i += 2;
                continue;
            }
        }

        if c == ' ' || c == '\t' || c == '\n' || c == '\r' {
            let next = if i + 1 < chars.len() {
                chars[i + 1]
            } else {
                '\0'
            };
            let prev_is_op = matches!(
                prev_char,
                '+' | '-'
                    | '*'
                    | '/'
                    | '%'
                    | '&'
                    | '|'
                    | '^'
                    | '~'
                    | '='
                    | '!'
                    | '<'
                    | '>'
                    | '?'
                    | ':'
                    | ','
                    | ';'
                    | '('
                    | '['
                    | '{'
            );
            let next_is_op = matches!(
                next,
                '+' | '-'
                    | '*'
                    | '/'
                    | '%'
                    | '&'
                    | '|'
                    | '^'
                    | '~'
                    | '='
                    | '!'
                    | '<'
                    | '>'
                    | '?'
                    | ':'
                    | ','
                    | ';'
                    | ')'
                    | ']'
                    | '}'
                    | '.'
            );
            if !prev_is_op && !next_is_op {
                output.push(' ');
            }
            i += 1;
            continue;
        }

        output.push(c);
        prev_char = c;
        i += 1;
    }

    output
}

pub fn minify_ast(program: &Program) -> Result<String, GenerationError> {
    let mut ast = Arena::new();
    let mut printer = Printer::new();
    printer.print_program(program, &mut ast)
}