futilehdl/src/parser/module.rs

108 lines
2.5 KiB
Rust
Raw Normal View History

2022-01-16 21:06:52 +00:00
use nom::{
branch::alt,
2022-02-02 00:03:03 +00:00
combinator::map,
2022-01-16 21:10:52 +00:00
error::context,
2022-01-23 23:10:09 +00:00
multi::{many0, separated_list0},
2022-02-02 00:03:03 +00:00
sequence::{delimited, preceded, tuple},
2022-01-16 21:06:52 +00:00
};
use crate::parser::{
2022-02-02 00:03:03 +00:00
assign_statement, declaration,
2022-01-17 16:37:15 +00:00
proc::{proc_block, ProcBlock},
2022-02-02 00:03:03 +00:00
tokens::{token, TokenKind as tk, TokenSpan},
typename, Assign, IResult, NetDecl, Span,
2022-01-16 21:06:52 +00:00
};
#[derive(Debug)]
pub enum PortDirection {
Input,
Output,
}
#[derive(Debug)]
pub struct PortDecl<'a> {
pub direction: PortDirection,
pub net: NetDecl<'a>,
}
#[derive(Debug)]
pub struct Module<'a> {
2022-01-23 23:10:09 +00:00
pub name: Span<'a>,
2022-01-16 21:06:52 +00:00
pub ports: Vec<PortDecl<'a>>,
pub items: Vec<ModuleItem<'a>>,
}
#[derive(Debug)]
pub enum ModuleItem<'a> {
Assign(Assign<'a>),
Proc(ProcBlock<'a>),
}
2022-02-02 00:00:11 +00:00
fn port_decl(i: TokenSpan) -> IResult<TokenSpan, PortDecl> {
map(declaration, |net| PortDecl {
2022-02-01 18:46:06 +00:00
direction: PortDirection::Input,
net,
})(i)
2022-01-16 21:06:52 +00:00
}
2022-02-02 00:00:11 +00:00
fn inputs_list(input: TokenSpan) -> IResult<TokenSpan, Vec<PortDecl>> {
separated_list0(token(tk::Comma), port_decl)(input)
2022-01-16 21:06:52 +00:00
}
2022-02-02 00:00:11 +00:00
fn assign_item(input: TokenSpan) -> IResult<TokenSpan, Assign> {
2022-01-17 00:15:27 +00:00
context(
"assignment",
2022-02-02 00:00:11 +00:00
delimited(token(tk::Assign), assign_statement, token(tk::Semicolon)),
2022-01-17 00:15:27 +00:00
)(input)
}
2022-02-02 00:00:11 +00:00
fn module_item(input: TokenSpan) -> IResult<TokenSpan, ModuleItem> {
2022-01-16 21:06:52 +00:00
alt((
2022-01-17 14:54:16 +00:00
map(assign_item, ModuleItem::Assign),
2022-01-16 21:10:52 +00:00
map(proc_block, ModuleItem::Proc),
2022-01-16 21:06:52 +00:00
))(input)
}
2022-02-02 00:00:11 +00:00
pub fn module(input: TokenSpan) -> IResult<TokenSpan, Module> {
2022-01-16 21:06:52 +00:00
context(
"module",
map(
tuple((
2022-02-02 00:00:11 +00:00
token(tk::Module),
token(tk::Ident),
delimited(token(tk::LParen), inputs_list, token(tk::RParen)),
preceded(token(tk::RArrow), typename),
delimited(token(tk::LBrace), many0(module_item), token(tk::RBrace)),
2022-01-16 21:06:52 +00:00
)),
2022-02-02 00:03:03 +00:00
|(_, name, inputs, _ret, items)| Module {
2022-02-02 00:00:11 +00:00
// TODO: bring back returns
name: name.span(),
2022-01-23 23:10:09 +00:00
ports: inputs,
2022-01-16 21:06:52 +00:00
items,
},
),
)(input)
}
2022-01-17 14:54:16 +00:00
#[cfg(test)]
mod test {
use super::*;
use nom::combinator::all_consuming;
#[test]
fn test_decl() {
declaration("reg abcd".into()).unwrap();
}
#[test]
fn test_assignment_item() {
all_consuming(assign_item)(" assign a = b ; ".into()).unwrap();
all_consuming(assign_item)(" assign a = b | c ; ".into()).unwrap();
}
#[test]
fn test_module_item() {
all_consuming(module_item)(" assign a = b ;".into()).unwrap();
}
}