mod literals; use nom::{ self, branch::alt, bytes::complete::tag, character::complete::{alpha1, alphanumeric1, char, multispace0}, combinator::{map, opt, recognize}, error::ParseError, error::{context, convert_error, VerboseError}, multi::{many0, separated_list1}, sequence::{delimited, pair, preceded, terminated, tuple}, }; use crate::literals::{decimal, hexadecimal}; const REG_EXAMPLE: &'static str = "reg [0:15] msg = 16'hAAAA;"; // custom IResult type for verboseerror pub type IResult> = nom::IResult; fn ws0<'a, F: 'a, O, E: ParseError<&'a str>>( inner: F, ) -> impl FnMut(&'a str) -> IResult<&'a str, O, E> where F: FnMut(&'a str) -> IResult<&'a str, O, E>, { delimited(multispace0, inner, multispace0) } fn identifier(input: &str) -> IResult<&str, &str> { recognize(pair( alt((alpha1, tag("_"))), many0(alt((alphanumeric1, tag("_")))), ))(input) } fn widthspec(input: &str) -> IResult<&str, u64> { delimited(char('['), ws0(decimal), char(']'))(input) } fn intliteral(input: &str) -> IResult<&str, (u64, u64)> { tuple((terminated(decimal, char('\'')), alt((decimal, hexadecimal))))(input) } #[derive(Debug)] struct NetDecl { name: String, width: Option, value: Option<(u64, u64)>, } #[derive(Debug)] enum PortDirection { Input, Output, } #[derive(Debug)] struct PortDecl { direction: PortDirection, net: NetDecl, } #[derive(Debug)] struct Module { name: String, ports: Vec, } fn declaration(i: &str) -> IResult<&str, NetDecl> { let (i, (_, width, ident, value)) = tuple(( ws0(alt((tag("reg"), tag("wire")))), opt(ws0(widthspec)), identifier, opt(preceded(ws0(char('=')), intliteral)), ))(i)?; Ok(( i, NetDecl { name: ident.into(), width, value, }, )) } fn port_decl(i: &str) -> IResult<&str, PortDecl> { map( tuple(( alt(( map(tag("input"), |_| PortDirection::Input), map(tag("output"), |_| PortDirection::Output), )), declaration, )), |(direction, net)| PortDecl { direction, net }, )(i) } fn ports_list(input: &str) -> IResult<&str, Vec> { context( "port declaration", separated_list1(ws0(char(',')), ws0(port_decl)), )(input) } fn module(input: &str) -> IResult<&str, Module> { context( "module", map( tuple(( tag("module"), ws0(identifier), ws0(delimited(char('('), ws0(ports_list), char(')'))), )), |(_, name, ports)| Module { name: name.into(), ports, }, ), )(input) } fn main() { let input = include_str!("../identity.fut"); let parsed = module(input); match parsed { Err(nom::Err::Error(err) | nom::Err::Failure(err)) => { print!("{}", convert_error(input, err)) } Err(_) => (), Ok(res) => println!("{:#?}", res), } } #[cfg(test)] mod test { use super::*; #[test] fn test_decl() { declaration("input reg abcd").unwrap(); } }