xshade-parser 0.1.2

Parser and untyped AST for the xshade language.
Documentation
use ::parser::*;

named!(pub parse_unary<NomSpan, Expression>,
    do_parse!(
        prefix: parse_unary_prefix >>
        primary: parse_primary >>
        postfix: parse_unary_postfix >>
    (fold_unary(primary, prefix, postfix)))
);

fn fold_unary(mut primary: Expression, mut prefix: Vec<(Span, UnaryOperatorType)>, mut postfix: Vec<UnaryExpressionData>) -> Expression {
    postfix.reverse();
    while let Some(unary_expression_data) = postfix.pop() {
        primary = match unary_expression_data {
            UnaryExpressionData::Field(span, identifier) => Expression::FieldAccessor(FieldAccessorExpression {
                span: Span::from_to(primary.get_span(), span),
                accessee_expression: Box::new(primary),
                field_name: identifier,
            }),
            UnaryExpressionData::Index(span, expression) => Expression::IndexAccessor(IndexAccesorExpression {
                span: Span::from_to(primary.get_span(), span),
                indexee_expression: Box::new(primary),
                index_expression: Box::new(expression),
            }),
        }
    }

    while let Some((span, operator)) = prefix.pop() {
        primary = Expression::Unary(UnaryExpression {
            span: Span::from_to(span, primary.get_span()),
            operator: operator,
            expression: Box::new(primary),
        });
    }

    primary
}

named!(parse_unary_prefix<NomSpan, Vec<(Span, UnaryOperatorType)>>,
    many0!(
        do_parse!(
            operator: alt!(
                tag!("-") |
                tag!("!") |
                tag!("~")
            ) >>
            ((Span::from_nom_span(&operator), parse_unary_operator_type(&operator)))
        )
    )
);

named!(parse_unary_postfix<NomSpan, Vec<UnaryExpressionData>>,
    many0!(alt!(
        parse_indexing |
        parse_field
    ))
);

#[derive(Debug)]
enum UnaryExpressionData {
    Index(Span, Expression),
    Field(Span, String),
}

named!(parse_field<NomSpan, UnaryExpressionData>,
    do_parse!(
        ws0 >>
        dot: tag!(".") >>
        accessor: recognize!(
            do_parse!(
                one_of!("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") >>
                many0!(one_of!("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")) >>
                ()
            )
        ) >>
        ws0 >>
    (UnaryExpressionData::Field(Span::from_to(Span::from_nom_span(&dot), Span::from_nom_span(&accessor)), accessor.fragment.to_string())))
);

named!(parse_indexing<NomSpan, UnaryExpressionData>,
    do_parse!(
        ws0 >>
        open_tag: tag!("[") >>
        ws0 >>
        indexer: parse_expression >>
        ws0 >>
        close_tag: tag!("]") >>
    (UnaryExpressionData::Index(Span::from_to(Span::from_nom_span(&open_tag), Span::from_nom_span(&close_tag)), indexer)))
);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = parse_expression(NomSpan::new(CompleteStr("-b[a].c"))).unwrap();
        assert!(result.0.fragment.len() == 0);
    }
}