futilehdl/src/parser/proc.rs

120 lines
2.9 KiB
Rust
Raw Normal View History

2022-01-16 21:06:52 +00:00
use nom::{
2022-01-17 00:15:27 +00:00
branch::alt,
2022-01-16 21:10:52 +00:00
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::{
2022-02-02 00:03:03 +00:00
assign_statement, expression,
tokens::{token, TokenKind as tk, TokenSpan},
Assign, Expression, IResult, Span,
2022-01-17 16:37:15 +00:00
};
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> {
pub expr: Expression<'a>,
pub arms: Vec<(Expression<'a>, ProcStatement<'a>)>,
2022-01-17 00:15:27 +00:00
}
2022-02-02 00:00:11 +00:00
fn match_arm(input: TokenSpan) -> IResult<TokenSpan, (Expression, ProcStatement)> {
separated_pair(expression, token(tk::FatArrow), proc_statement)(input)
2022-01-17 00:15:27 +00:00
}
2022-02-02 00:00:11 +00:00
fn match_block(input: TokenSpan) -> IResult<TokenSpan, MatchBlock> {
2022-01-17 00:15:27 +00:00
context(
"match block",
map(
tuple((
2022-02-02 00:00:11 +00:00
token(tk::Match),
delimited(token(tk::LParen), expression, token(tk::RParen)),
delimited(
token(tk::LBrace),
separated_list1(token(tk::Comma), match_arm),
token(tk::RBrace),
),
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)
}
2022-02-02 00:00:11 +00:00
fn statement_block(input: TokenSpan) -> IResult<TokenSpan, Vec<ProcStatement>> {
2022-01-17 16:37:15 +00:00
delimited(
2022-02-02 00:00:11 +00:00
token(tk::LBrace),
separated_list1(token(tk::Semicolon), proc_statement),
token(tk::RBrace),
2022-01-17 16:37:15 +00:00
)(input)
2022-01-16 21:06:52 +00:00
}
/// parse a statement that is valid inside a proc block
2022-02-02 00:00:11 +00:00
fn proc_statement(input: TokenSpan) -> IResult<TokenSpan, 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
}
2022-02-02 00:00:11 +00:00
pub fn proc_block(input: TokenSpan) -> IResult<TokenSpan, ProcBlock> {
2022-01-16 21:06:52 +00:00
context(
"proc block",
map(
tuple((
2022-02-02 00:00:11 +00:00
token(tk::Proc),
delimited(token(tk::LParen), token(tk::Ident), token(tk::RParen)),
delimited(token(tk::LBrace), many1(proc_statement), token(tk::RBrace)),
2022-01-16 21:06:52 +00:00
)),
2022-02-02 00:00:11 +00:00
|(_, net, items)| ProcBlock {
net: net.span(),
items,
},
2022-01-16 21:06:52 +00:00
),
)(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();
}
}