2022-01-16 21:06:52 +00:00
|
|
|
use nom::{
|
2022-01-17 00:15:27 +00:00
|
|
|
branch::alt,
|
2022-01-16 21:06:52 +00:00
|
|
|
bytes::complete::tag,
|
2022-01-16 21:10:52 +00:00
|
|
|
character::complete::char,
|
|
|
|
combinator::map,
|
|
|
|
error::context,
|
2022-01-17 16:37:52 +00:00
|
|
|
multi::{many1, separated_list1},
|
2022-01-17 16:37:15 +00:00
|
|
|
sequence::{delimited, separated_pair, tuple},
|
2022-01-16 21:06:52 +00:00
|
|
|
};
|
|
|
|
|
2022-01-17 16:37:15 +00:00
|
|
|
use crate::parser::{
|
|
|
|
assign_statement, expression, identifier, ws0, Assign, Expression, IResult, Span,
|
|
|
|
};
|
2022-01-16 21:06:52 +00:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ProcBlock<'a> {
|
|
|
|
pub net: Span<'a>,
|
|
|
|
pub items: Vec<ProcStatement<'a>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ProcStatement<'a> {
|
|
|
|
IfElse(IfElseBlock),
|
2022-01-17 00:15:27 +00:00
|
|
|
Assign(Assign<'a>),
|
2022-01-16 21:06:52 +00:00
|
|
|
Match(MatchBlock<'a>),
|
2022-01-17 00:15:27 +00:00
|
|
|
Block(Vec<ProcStatement<'a>>),
|
2022-01-16 21:06:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: postponed because annoying to implement
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct IfElseBlock {}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MatchBlock<'a> {
|
2022-01-17 14:37:07 +00:00
|
|
|
pub expr: Expression<'a>,
|
|
|
|
pub arms: Vec<(Expression<'a>, ProcStatement<'a>)>,
|
2022-01-17 00:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn match_arm(input: Span) -> IResult<Span, (Expression, ProcStatement)> {
|
|
|
|
separated_pair(ws0(expression), tag("=>"), ws0(proc_statement))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn match_block(input: Span) -> IResult<Span, MatchBlock> {
|
|
|
|
context(
|
|
|
|
"match block",
|
|
|
|
map(
|
|
|
|
tuple((
|
|
|
|
ws0(tag("match")),
|
|
|
|
ws0(delimited(char('('), ws0(expression), char(')'))),
|
2022-01-17 16:37:15 +00:00
|
|
|
ws0(delimited(
|
|
|
|
char('{'),
|
|
|
|
separated_list1(char(','), ws0(match_arm)),
|
|
|
|
char('}'),
|
|
|
|
)),
|
2022-01-17 00:15:27 +00:00
|
|
|
)),
|
2022-01-17 16:37:15 +00:00
|
|
|
|(_, expr, arms)| MatchBlock { expr, arms },
|
2022-01-17 00:15:27 +00:00
|
|
|
),
|
|
|
|
)(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn statement_block(input: Span) -> IResult<Span, Vec<ProcStatement>> {
|
2022-01-17 16:37:15 +00:00
|
|
|
delimited(
|
|
|
|
char('{'),
|
|
|
|
separated_list1(char(';'), ws0(proc_statement)),
|
|
|
|
char('}'),
|
|
|
|
)(input)
|
2022-01-16 21:06:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// parse a statement that is valid inside a proc block
|
|
|
|
fn proc_statement(input: Span) -> IResult<Span, ProcStatement> {
|
2022-01-17 00:15:27 +00:00
|
|
|
alt((
|
|
|
|
map(match_block, ProcStatement::Match),
|
|
|
|
map(statement_block, ProcStatement::Block),
|
|
|
|
map(assign_statement, ProcStatement::Assign),
|
|
|
|
))(input)
|
2022-01-16 21:06:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
|
|
|
|
context(
|
|
|
|
"proc block",
|
|
|
|
map(
|
|
|
|
tuple((
|
|
|
|
ws0(tag("proc")),
|
|
|
|
ws0(delimited(char('('), ws0(identifier), char(')'))),
|
2022-01-17 00:15:27 +00:00
|
|
|
ws0(delimited(char('{'), many1(ws0(proc_statement)), char('}'))),
|
2022-01-16 21:06:52 +00:00
|
|
|
)),
|
|
|
|
|(_, net, items)| ProcBlock { net, items },
|
|
|
|
),
|
|
|
|
)(input)
|
|
|
|
}
|
2022-01-17 00:15:27 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_statement() {
|
|
|
|
proc_statement(" abc = def ".into()).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_match_arm() {
|
|
|
|
match_arm(" 1 => abc = def ".into()).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_match_block() {
|
|
|
|
let input = "
|
|
|
|
match (asdf) {
|
|
|
|
1 => a = 0,
|
|
|
|
2 => c = ~d
|
|
|
|
}
|
|
|
|
";
|
|
|
|
match_block(input.into()).unwrap();
|
|
|
|
}
|
|
|
|
}
|