90 lines
2.2 KiB
Rust
90 lines
2.2 KiB
Rust
|
use nom::{
|
||
|
branch::alt,
|
||
|
bytes::complete::tag,
|
||
|
character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, u64 as decimal},
|
||
|
combinator::{consumed, map, opt, recognize},
|
||
|
error::{context, ParseError, VerboseError},
|
||
|
multi::{many0, many1, separated_list0},
|
||
|
sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
|
||
|
};
|
||
|
|
||
|
use crate::parser::proc::{proc_block, ProcBlock};
|
||
|
use crate::parser::{
|
||
|
assign_statement, declaration, identifier, intliteral, widthspec, ws0, Assign, IResult,
|
||
|
NetDecl, Span,
|
||
|
};
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum PortDirection {
|
||
|
Input,
|
||
|
Output,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct PortDecl<'a> {
|
||
|
pub pos: Span<'a>,
|
||
|
pub direction: PortDirection,
|
||
|
pub net: NetDecl<'a>,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct Module<'a> {
|
||
|
pub name: &'a str,
|
||
|
pub ports: Vec<PortDecl<'a>>,
|
||
|
pub items: Vec<ModuleItem<'a>>,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum ModuleItem<'a> {
|
||
|
Assign(Assign<'a>),
|
||
|
Proc(ProcBlock<'a>),
|
||
|
}
|
||
|
|
||
|
fn port_decl(i: Span) -> IResult<Span, PortDecl> {
|
||
|
map(
|
||
|
consumed(tuple((
|
||
|
alt((
|
||
|
map(tag("input"), |_| PortDirection::Input),
|
||
|
map(tag("output"), |_| PortDirection::Output),
|
||
|
)),
|
||
|
declaration,
|
||
|
))),
|
||
|
|(pos, (direction, net))| PortDecl {
|
||
|
pos,
|
||
|
direction,
|
||
|
net,
|
||
|
},
|
||
|
)(i)
|
||
|
}
|
||
|
|
||
|
fn ports_list(input: Span) -> IResult<Span, Vec<PortDecl>> {
|
||
|
separated_list0(ws0(char(',')), ws0(port_decl))(input)
|
||
|
}
|
||
|
|
||
|
fn module_item(input: Span) -> IResult<Span, ModuleItem> {
|
||
|
alt((
|
||
|
map(assign_statement, |assig| ModuleItem::Assign(assig)),
|
||
|
map(proc_block, |proc| ModuleItem::Proc(proc)),
|
||
|
))(input)
|
||
|
}
|
||
|
|
||
|
/// parse a top-level module declaration
|
||
|
pub fn module(input: Span) -> IResult<Span, Module> {
|
||
|
context(
|
||
|
"module",
|
||
|
map(
|
||
|
tuple((
|
||
|
tag("module"),
|
||
|
ws0(identifier),
|
||
|
ws0(delimited(char('('), ws0(ports_list), char(')'))),
|
||
|
ws0(delimited(char('{'), many1(ws0(module_item)), char('}'))),
|
||
|
)),
|
||
|
|(_, name, ports, items)| Module {
|
||
|
name: (*name.fragment()),
|
||
|
ports,
|
||
|
items,
|
||
|
},
|
||
|
),
|
||
|
)(input)
|
||
|
}
|