//Take a single token and convert it into a snippet of Rust code
Take a single token and convert it into a snippet of Rust code
Take a single token and convert it into a snippet of Rust code
fn translate_token(token: & Token, code: & mut String) -> Result<(), String> {
    match token {
        Token::If(modifier, decision, stop_or_break) => {
            code.push_str("if ");
            //Decision
            match decision {
                Decision::CharacterSet(range_list) => {
                    let mut range_list = range_list.into_iter();
                    range_to_snippet(range_list.next().unwrap(), code);
                    for range in range_list {
                        code.push_str(" || ");
                        range_to_snippet(range, code);
                    }
                }
                Decision::Literal(character) => {
                    code.push_str("(character.current().unwrap() as u32) == ");
                    code.push_str(format!("{}", character).as_str());
                }
                Decision::LiteralString(_) => {
                    return Err(String::from("Literal strings not supported yet."));
                }
                Decision::CountEquals(n) => {
                    code.push_str("match_count == ");
                    code.push_str(format!("{}", n).as_str());
                }
                Decision::CountLessThan(n) => {
                    code.push_str("match_count < ");
                    code.push_str(format!("{}", n).as_str());
                }
                Decision::Anchor(anchor_type, anchor_location) => {
                    match anchor_location {
                        AnchorLocation::Start => {
                            match anchor_type {
                                AnchorType::Regular => {
                                    code.push_str("character.previous() == native_regex_lib::native_regex::character::Previous::Start");
                                }
                                AnchorType::Newline => {
                                    code.push_str("character.previous() == native_regex_lib::native_regex::character::Previous::Character('\\n') || character.previous() == native_regex_lib::native_regex::character::Previous::Start");
                                }
                            }
                        }
                        AnchorLocation::End => {
                            match anchor_type {
                                AnchorType::Regular => {
                                    code.push_str("character.current().is_none()");
                                }
                                AnchorType::Newline => {
                                    code.push_str("{ if character.current().is_some() { if character.current().unwrap() != '\\n' { false } else { true } } else { true } }");
                                }
                            }
                        }
                    }
                }
                Decision::WordBoundary(boundary_type) => {
                    match boundary_type {
                        WordBoundaryType::Byte => {
                            code.push_str("{ if character.previous() != native_regex_lib::native_regex::character::Previous::Start && character.current().is_some() {
    if (Self::is_word_byte(character.previous().unwrap()) || !Self::is_word_byte(character.current().unwrap())) &&
        (!Self::is_word_byte(character.previous().unwrap()) || Self::is_word_byte(character.current().unwrap())) {
        false
    } else {
        true
    }
} else {
    if character.previous() == native_regex_lib::native_regex::character::Previous::Start && !Self::is_word_byte(character.current().unwrap()) || character.current().is_none() && !Self::is_word_byte(character.previous().unwrap()) {
        false
    } else {
        true
    }
} }");
                        }
                        WordBoundaryType::Character => {
                            code.push_str("{ if character.previous() != native_regex_lib::native_regex::character::Previous::Start && character.current().is_some() {
    if (Self::is_word_character(character.previous().unwrap()) || !Self::is_word_character(character.current().unwrap())) &&
        (!Self::is_word_character(character.previous().unwrap()) || Self::is_word_character(character.current().unwrap())) {
        false
    } else {
        true
    }
} else {
    if character.previous() == native_regex_lib::native_regex::character::Previous::Start && !Self::is_word_character(character.current().unwrap()) || character.current().is_none() && !Self::is_word_character(character.previous().unwrap()) {
        false
    } else {
        true
    }
} }");
                        }
                    }
                }
                Decision::Middle => {
                    code.push_str("character.current().is_some()");
                }
            }
            //Cheaty invert the logic by using else
            if *modifier == Modifier::Not {
                code.push_str(" {  } else ");
            }
            //Body
            code.push_str(" { ");
            code.push_str(match stop_or_break {
                NoMatch::Stop => {
                    "return None;"
                }
                NoMatch::Break => {
                    "break;"
                }
            });
            code.push_str(" }\n\n");
        }
        Token::While(decision, block) => {
            code.push_str("while ");
            match decision {
                Decision::Middle => {
                    code.push_str("character.current().is_some() ")
                }
                _ => { unreachable!() }
            }
            translate_token(block.as_ref(), code)?;
        }
        Token::StartCount => {
            code.push_str("let mut match_count = 0;\n\n");
        }
        Token::IncrementCount => {
            code.push_str("match_count += 1;\n\n");
        }
        Token::Advance => {
            code.push_str("character = chars.advance();\n\n");
        }
        Token::Capture(index, token_list) => {
            let index = format!("{}", index);
            //Start of capture
            code.push_str("let capture_");
            code.push_str(index.as_str());
            code.push_str("_start = character.index();\n\n");
            //Capture body
            for element in token_list {
                translate_token(element, code)?;
            }
            //End of capture
            code.push_str("captures.insert(");
            code.push_str(index.as_str());
            code.push_str(", (capture_");
            code.push_str(index.as_str());
            code.push_str("_start, character.index()));\n\n");
        }
        Token::Block(token_list) => {
            code.push_str("{\n\n");
            for element in token_list {
                translate_token(element, code)?;
            }
            code.push_str("}\n\n")
        }
        Token::Empty => {}
    }
    Ok(())
}
fn translate_token ( token : & Token , code : & mut String ) -> Result < ( ) , String > { match token { Token :: If ( modifier , decision , stop_or_break ) => { code . push_str ( " " ) ; //Decision match decision { Decision :: CharacterSet ( range_list ) => { let mut range_list = range_list . into_iter ( ) ; range_to_snippet ( range_list . next ( ) . unwrap ( ) , code ) ; for range in range_list { code . push_str ( " " ) ; range_to_snippet ( range , code ) ; } } Decision :: Literal ( character ) => { code . push_str ( " " ) ; code . push_str ( format ! ( " " character ) . as_str ( ) ) ; } Decision :: LiteralString ( _ ) => { return Err ( String :: from ( " " ) ) ; } Decision :: CountEquals ( n ) => { code . push_str ( " " ) ; code . push_str ( format ! ( " " n ) . as_str ( ) ) ; } Decision :: CountLessThan ( n ) => { code . push_str ( " " ) ; code . push_str ( format ! ( " " n ) . as_str ( ) ) ; } Decision :: Anchor ( anchor_type , anchor_location ) => { match anchor_location { AnchorLocation :: Start => { match anchor_type { AnchorType :: Regular => { code . push_str ( " " ) ; } AnchorType :: Newline => { code . push_str ( " \\ " ) ; } } } AnchorLocation :: End => { match anchor_type { AnchorType :: Regular => { code . push_str ( " " ) ; } AnchorType :: Newline => { code . push_str ( " \\ " ) ; } } } } } Decision :: WordBoundary ( boundary_type ) => { match boundary_type { WordBoundaryType :: Byte => { code . push_str ( " " ) ; } WordBoundaryType :: Character => { code . push_str ( " " ) ; } } } Decision :: Middle => { code . push_str ( " " ) ; } } //Cheaty invert the logic by using else if * modifier == Modifier :: Not { code . push_str ( " " ) ; } //Body code . push_str ( " " ) ; code . push_str ( match stop_or_break { NoMatch :: Stop => { " " } NoMatch :: Break => { " " } } ) ; code . push_str ( " \n \n " ) ; } Token :: While ( decision , block ) => { code . push_str ( " " ) ; match decision { Decision :: Middle => { code . push_str ( " " ) } _ => { unreachable ! ( ) } } translate_token ( block . as_ref ( ) , code ) ? ; } Token :: StartCount => { code . push_str ( " \n \n " ) ; } Token :: IncrementCount => { code . push_str ( " \n \n " ) ; } Token :: Advance => { code . push_str ( " \n \n " ) ; } Token :: Capture ( index , token_list ) => { let index = format ! ( " " index ) ; //Start of capture code . push_str ( " " ) ; code . push_str ( index . as_str ( ) ) ; code . push_str ( " \n \n " ) ; //Capture body for element in token_list { translate_token ( element , code ) ? ; } //End of capture code . push_str ( " " ) ; code . push_str ( index . as_str ( ) ) ; code . push_str ( " " ) ; code . push_str ( index . as_str ( ) ) ; code . push_str ( " \n \n " ) ; } Token :: Block ( token_list ) => { code . push_str ( " \n \n " ) ; for element in token_list { translate_token ( element , code ) ? ; } code . push_str ( " \n \n " ) } Token :: Empty => { } } Ok ( ( ) ) }
Take a single token and convert it into a snippet of Rust code
Take a single token and convert it into a snippet of Rust code
token
& Token
code
& mut String