use crate::attributes::*; use crate::expressions::*; use crate::identifiers::*; use crate::primaries::*; use crate::util::*; use nom::branch::*; use nom::bytes::complete::*; use nom::combinator::*; use nom::multi::*; use nom::sequence::*; use nom::IResult; // ----------------------------------------------------------------------------- #[derive(Debug)] pub struct TfCall<'a> { pub identifier: ScopedIdentifier<'a>, pub attribute: Vec>, pub argument: Option>, } #[derive(Debug)] pub struct SystemTfCall<'a> { pub identifier: Identifier<'a>, pub argument: Option>, pub data_type: Option>, pub expression: Option>>, pub clocking_event: Option>, } #[derive(Debug)] pub enum SubroutineCall<'a> { Tf(Box>), SystemTf(Box>), Method(Box>), Randomize(Box>), StdRandomize(Box>), } #[derive(Debug)] pub struct ListOfArguments<'a> { pub unnamed: Vec>, pub named: Vec<(Identifier<'a>, Option>)>, } #[derive(Debug)] pub struct MethodCall<'a> { pub root: MethodCallRoot<'a>, pub body: MethodCallBody<'a>, } #[derive(Debug)] pub enum MethodCallRoot<'a> { Primary(Primary<'a>), ImplicitClassHandle(Scope<'a>), } #[derive(Debug)] pub enum MethodCallBody<'a> { User(MethodCallBodyUser<'a>), Array(ArrayManipulationCall<'a>), Randomize(RandomizeCall<'a>), } #[derive(Debug)] pub struct MethodCallBodyUser<'a> { pub identifier: Identifier<'a>, pub attribute: Vec>, pub argument: Option>, } #[derive(Debug)] pub struct ArrayManipulationCall<'a> { pub name: ArrayMethodName<'a>, pub attribute: Vec>, pub argument: Option>, pub with: Option>, } #[derive(Debug)] pub struct RandomizeCall<'a> { pub attribute: Vec>, pub argument: Vec>, pub with: Vec>, pub constraint_block: Option>, } #[derive(Debug)] pub enum ArrayMethodName<'a> { Identifier(Identifier<'a>), Unique, And, Or, Xor, } // ----------------------------------------------------------------------------- pub fn constant_function_call(s: &str) -> IResult<&str, SubroutineCall> { function_subroutine_call(s) } pub fn tf_call(s: &str) -> IResult<&str, TfCall> { let (s, identifier) = ps_or_hierarchical_tf_identifier(s)?; let (s, attribute) = many0(sp(attribute_instance))(s)?; let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?; Ok(( s, TfCall { identifier, attribute, argument, }, )) } pub fn system_tf_call(s: &str) -> IResult<&str, SystemTfCall> { alt(( system_tf_call_list_of_arguments, system_tf_call_data_type, system_tf_call_clocking_event, ))(s) } pub fn system_tf_call_list_of_arguments(s: &str) -> IResult<&str, SystemTfCall> { let (s, identifier) = system_tf_identifier(s)?; let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?; Ok(( s, SystemTfCall { identifier, argument, data_type: None, expression: None, clocking_event: None, }, )) } pub fn system_tf_call_data_type(s: &str) -> IResult<&str, SystemTfCall> { let (s, identifier) = system_tf_identifier(s)?; let (s, _) = sp(tag("("))(s)?; let (s, data_type) = sp(data_type)(s)?; let (s, expression) = sp(preceded(sp(tag(",")), expression))(s)?; let (s, _) = sp(tag(")"))(s)?; let data_type = Some(data_type); let expression = Some(vec![expression]); Ok(( s, SystemTfCall { identifier, argument: None, data_type, expression, clocking_event: None, }, )) } pub fn system_tf_call_clocking_event(s: &str) -> IResult<&str, SystemTfCall> { let (s, identifier) = system_tf_identifier(s)?; let (s, _) = sp(tag("("))(s)?; let (s, expression) = separated_nonempty_list(sp(tag(",")), sp(expression))(s)?; let (s, clocking_event) = opt(preceded(sp(tag(",")), opt(sp(clocking_event))))(s)?; let (s, _) = sp(tag(")"))(s)?; let expression = Some(expression); let clocking_event = if let Some(Some(x)) = clocking_event { Some(x) } else { None }; Ok(( s, SystemTfCall { identifier, argument: None, data_type: None, expression, clocking_event, }, )) } pub fn subroutine_call(s: &str) -> IResult<&str, SubroutineCall> { alt(( map(tf_call, |x| SubroutineCall::Tf(Box::new(x))), map(system_tf_call, |x| SubroutineCall::SystemTf(Box::new(x))), map(method_call, |x| SubroutineCall::Method(Box::new(x))), map( tuple((tag("std"), sp(tag("::")), randomize_call)), |(_, _, x)| SubroutineCall::StdRandomize(Box::new(x)), ), map(randomize_call, |x| SubroutineCall::Randomize(Box::new(x))), ))(s) } pub fn function_subroutine_call(s: &str) -> IResult<&str, SubroutineCall> { subroutine_call(s) } pub fn list_of_arguments(s: &str) -> IResult<&str, ListOfArguments> { let (s, unnamed) = separated_list(sp(tag(",")), sp(expression))(s)?; let (s, named) = separated_list( sp(tag(",")), pair( preceded(tag("."), identifier), delimited(sp(tag("(")), opt(sp(expression)), sp(tag(")"))), ), )(s)?; Ok((s, ListOfArguments { unnamed, named })) } pub fn method_call(s: &str) -> IResult<&str, MethodCall> { let (s, root) = method_call_root(s)?; let (s, _) = sp(tag("."))(s)?; let (s, body) = method_call_body(s)?; Ok((s, MethodCall { root, body })) } pub fn method_call_body(s: &str) -> IResult<&str, MethodCallBody> { alt((method_call_body_user, built_in_method_call))(s) } pub fn method_call_body_user(s: &str) -> IResult<&str, MethodCallBody> { let (s, identifier) = method_identifier(s)?; let (s, attribute) = many0(sp(attribute_instance))(s)?; let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?; Ok(( s, MethodCallBody::User(MethodCallBodyUser { identifier, attribute, argument, }), )) } pub fn built_in_method_call(s: &str) -> IResult<&str, MethodCallBody> { alt(( map(array_manipulation_call, |x| MethodCallBody::Array(x)), map(randomize_call, |x| MethodCallBody::Randomize(x)), ))(s) } pub fn array_manipulation_call(s: &str) -> IResult<&str, ArrayManipulationCall> { let (s, name) = array_method_name(s)?; let (s, attribute) = many0(sp(attribute_instance))(s)?; let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?; let (s, with) = opt(preceded( sp(tag("with")), delimited(sp(tag("(")), sp(expression), sp(tag(")"))), ))(s)?; Ok(( s, ArrayManipulationCall { name, attribute, argument, with, }, )) } pub fn randomize_call(s: &str) -> IResult<&str, RandomizeCall> { let (s, _) = tag("randomize")(s)?; let (s, attribute) = many0(sp(attribute_instance))(s)?; let (s, argument) = opt(delimited( sp(tag("(")), opt(alt(( sp(variable_identifier_list), map(sp(tag("null")), |_| vec![]), ))), sp(tag(")")), ))(s)?; let (s, with) = opt(tuple(( sp(tag("with")), opt(delimited( sp(tag("(")), opt(sp(identifier_list)), sp(tag(")")), )), constraint_block, )))(s)?; let argument = if let Some(Some(x)) = argument { x } else { vec![] }; let (with, constraint_block) = if let Some((_, Some(Some(x)), y)) = with { (x, Some(y)) } else { (vec![], None) }; Ok(( s, RandomizeCall { attribute, argument, with, constraint_block, }, )) } pub fn method_call_root(s: &str) -> IResult<&str, MethodCallRoot> { alt(( map(primary, |x| MethodCallRoot::Primary(x)), map(implicit_class_handle, |x| { MethodCallRoot::ImplicitClassHandle(x) }), ))(s) } pub fn array_method_name(s: &str) -> IResult<&str, ArrayMethodName> { alt(( map(tag("unique"), |_| ArrayMethodName::Unique), map(tag("and"), |_| ArrayMethodName::And), map(tag("or"), |_| ArrayMethodName::Or), map(tag("xor"), |_| ArrayMethodName::Xor), map(method_identifier, |x| ArrayMethodName::Identifier(x)), ))(s) } // -----------------------------------------------------------------------------