#[rustfmt::skip]
#[allow(unused)]
use nom::{
bytes::{
complete as byte_complete,
streaming as byte_streaming,
},
character::{
complete as char_complete,
streaming as char_streaming
},
complete as bit_complete,
streaming as bit_streaming,
};
use nom::{combinator::all_consuming, multi::many0, sequence::delimited, IResult, Parser};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expression {
Next,
Prev,
Increment,
Decrement,
Output,
Input,
Loop(Vec<Expression>),
Comment(String),
}
macro_rules! cmd_parser {
($pname:ident; $ch:literal -> $cmd:expr) => {
pub fn $pname(input: &str) -> IResult<&str, Expression> {
char_complete::char($ch).map(|_| $cmd).parse(input)
}
};
}
cmd_parser!(next_exp; '>' -> Expression::Next);
cmd_parser!(prev_exp; '<' -> Expression::Prev);
cmd_parser!(increment_exp; '+' -> Expression::Increment);
cmd_parser!(decrement_exp; '-' -> Expression::Decrement);
cmd_parser!(output_exp; '.' -> Expression::Output);
cmd_parser!(input_exp; ',' -> Expression::Input);
pub fn simple_exp(input: &str) -> IResult<&str, Expression> {
next_exp
.or(prev_exp)
.or(increment_exp)
.or(decrement_exp)
.or(output_exp)
.or(input_exp)
.parse(input)
}
pub fn loop_exp(input: &str) -> IResult<&str, Expression> {
delimited(
char_complete::char('['),
many0(exp),
char_complete::char(']'),
)
.map(|v| Expression::Loop(v))
.parse(input)
}
pub fn comment_exp(input: &str) -> IResult<&str, Expression> {
let (input, out) = byte_complete::is_not("><+-.,[]")(input)?;
Ok((input, Expression::Comment(out.to_string())))
}
pub fn exp(input: &str) -> IResult<&str, Expression> {
simple_exp.or(comment_exp).or(loop_exp).parse(input)
}
pub fn many_exp(input: &str) -> IResult<&str, Vec<Expression>> {
many0(exp)(input)
}
pub fn parse(input: &str) -> IResult<&str, Vec<Expression>> {
all_consuming(many_exp)(input)
}