prattle 0.1.3

General, configurable Pratt/TDOP parser.
Documentation
use std::fmt::{Display, Formatter, Error}; 

#[macro_use] extern crate prattle;

use prattle::prelude::*;

#[derive(Debug, Clone, PartialEq)]
pub enum CToken {
    Number(String), 
    Ident(String), 
    Add, Sub, 
    Mul, Div, Mod, 
    LParens, RParens
}

impl Display for CToken {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", match *self {
            CToken::Number(ref s) => format!("(Number: {})", s), 
            CToken::Ident(ref s) => format!("(Ident: {})", s), 
            CToken::Add => "Add".to_string(), 
            CToken::Sub => "Sub".to_string(),
            CToken::Mul => "Mul".to_string(),
            CToken::Div => "Div".to_string(),
            CToken::Mod => "Mod".to_string(),
            CToken::LParens => "(".to_string(),
            CToken::RParens => ")".to_string(),
        })
    }
}

fn token_spec() -> Result<ParserSpec<CToken>, SpecificationError<CToken>> {
    let mut spec = ParserSpec::new();
    add_null_assoc!(spec, PrecedenceLevel::Root, (CToken::Number("".to_string()), CToken::Ident("".to_string())) => |_, token: CToken, _| {
        Ok(Node::Simple(token.clone()))
    });
    add_left_assoc!(spec, PrecedenceLevel::First, (CToken::Add, CToken::Sub) => |parser, token, lbp, node| {
        Ok(Node::Composite { token: token.clone(), children: vec![node, parser.parse_expr(lbp)?] } )
    } );
    add_left_assoc!(spec, PrecedenceLevel::Second, (CToken::Mul, CToken::Div, CToken::Mod) => |parser, token, lbp, node| {
        Ok(Node::Composite { token: token.clone(), children: vec![node, parser.parse_expr(lbp)?] } )
    } );
    add_null_assoc!(spec, PrecedenceLevel::First, (CToken::LParens) => |parser, _, lbp| {
        let res = parser.parse_expr(lbp)?;
        parser.consume(CToken::RParens)?;
        Ok(res)
    });
    Ok(spec)
}

fn main() {
    let tokens = vec![
        CToken::Ident("a".to_string()), 
        CToken::Add,
        CToken::LParens,
        CToken::Number("10".to_string()), 
        CToken::Mul,
        CToken::LParens,
        CToken::Ident("b".to_string()),
        CToken::Div,
        CToken::Number("2".to_string()),
        CToken::RParens,
        CToken::Mod, 
        CToken::Number("4".to_string()),
        CToken::RParens,
        CToken::Sub,
        CToken::Ident("c".to_string()),
    ];
    let lexer = LexerVec::new(tokens);
    let spec = token_spec().expect("Should work.");
    let mut parser = GeneralParser::new(spec, lexer);
    let res = parser.parse();
    println!("{:?}", res);
}