blarse 0.1.0

A lightweight parsing framework for blex
Documentation
pub use super::parse_token::*;
pub use super::*;
pub use blex::token::*;


fn whitespace_rule(mut tokens: Vec<Token>) -> Option<Vec<Token>> {
    let ch = tokens[0].single_char().unwrap_or_default();
    if ch.is_whitespace() || ch == '\u{0}' {
        tokens[0].tags.push("ws");
    }
    Some(tokens)
}

fn paren_rule(mut tokens: Vec<Token>) -> Option<Vec<Token>> {
    let ch = tokens[0].single_char().unwrap_or_default();
    if ch == '(' || ch == ')' {
        tokens[0].tags.push("paren");
    }
    Some(tokens)
}

fn word_rule(tokens: Vec<Token>) -> Option<Vec<Token>> {
    let empty = &empty_token();
    let last_token = tokens.last().unwrap_or(empty);
    if !last_token.has_tag("ws") && !last_token.has_tag("paren") {
        None
    } else if tokens.len() == 1 {
        Some(tokens)
    } else {
        Some(vec![
            wrap(tokens[0..tokens.len() - 1].to_vec(), vec!["word"]),
            tokens.last().unwrap().clone(),
        ])
    }
}

fn remove_whitespace_rule(tokens: Vec<Token>) -> Option<Vec<Token>> {
    if tokens[0].has_tag("ws") {
        Some(vec![])
    } else {
        Some(tokens)
    }
}

fn s_expr_rules() -> Vec<impl Fn(Vec<Token>) -> Option<Vec<Token>>> {
    [
        whitespace_rule,
        paren_rule,
        word_rule,
        remove_whitespace_rule,
    ]
    .to_vec()
}

fn remove_last(mut pts: Vec<ParseToken>) -> Vec<ParseToken> {
    if pts.len() > 0 {
        pts.remove(pts.len() - 1);
    }
    pts
}

fn eval(mut pts: Vec<ParseToken>) -> Vec<ParseToken> {
    let mut l_index: Option<usize> = None;
    
    for i in 0..pts.len() {
        if pts[i].has_tag("(") {
            l_index = Some(i);
        } else if let Some(l) = l_index {
            if pts[i].has_tag(")") {
                let pts_slice = pts[(l + 1)..i].to_vec();
                let new_expr = ParseToken::new_branch_from_first(
                    eval(pts_slice), 
                    vec!["expr"]);
                pts.splice(l..=i, vec![new_expr]);
                return eval(pts);
            }
        }
    }
    pts
}

#[test]
pub fn parse_s_exprs() {
    let text = "
(define (rgb-series mk)
  (vc-append
   (series (lambda (sz) (colorize (mk sz) \"red\")))
   (series (lambda (sz) (colorize (mk sz) \"green\")))
   (series (lambda (sz) (colorize (mk sz) \"blue\")))))";

    let mut body = str_to_tokens(text);
    process_rules(s_expr_rules(), &mut body, false);

    println!("===   TOKENS   ===");
    print_tokens(body.clone());

    println!("===PARSE TOKENS===");

    let pts = tokens_to_parse_tokens(body);
    print_parse_tokens(remove_last(eval(pts)));
}

#[test]
pub fn parse_s_exprs2() {
    let text = "A (space)";

    let mut body = str_to_tokens(text);
    process_rules(s_expr_rules(), &mut body, false);

    println!("===   TOKENS   ===");
    print_tokens(body.clone());

    println!("===PARSE TOKENS===");

    let pts = tokens_to_parse_tokens(body);
    print_parse_tokens(remove_last(eval(pts)));
}