diff options
Diffstat (limited to 'macros/src/syntax/parse.rs')
-rw-r--r-- | macros/src/syntax/parse.rs | 363 |
1 files changed, 0 insertions, 363 deletions
diff --git a/macros/src/syntax/parse.rs b/macros/src/syntax/parse.rs deleted file mode 100644 index c78453a4..00000000 --- a/macros/src/syntax/parse.rs +++ /dev/null @@ -1,363 +0,0 @@ -mod app; -mod hardware_task; -mod idle; -mod init; -mod resource; -mod software_task; -mod util; - -use proc_macro2::TokenStream as TokenStream2; -use syn::{ - braced, parenthesized, - parse::{self, Parse, ParseStream, Parser}, - token::Brace, - Ident, Item, LitInt, Token, -}; - -use crate::syntax::{ - ast::{App, AppArgs, HardwareTaskArgs, IdleArgs, InitArgs, SoftwareTaskArgs, TaskLocal}, - Either, -}; - -// Parse the app, both app arguments and body (input) -pub fn app(args: TokenStream2, input: TokenStream2) -> parse::Result<App> { - let args = AppArgs::parse(args)?; - let input: Input = syn::parse2(input)?; - - App::parse(args, input) -} - -pub(crate) struct Input { - _mod_token: Token![mod], - pub ident: Ident, - _brace_token: Brace, - pub items: Vec<Item>, -} - -impl Parse for Input { - fn parse(input: ParseStream<'_>) -> parse::Result<Self> { - fn parse_items(input: ParseStream<'_>) -> parse::Result<Vec<Item>> { - let mut items = vec![]; - - while !input.is_empty() { - items.push(input.parse()?); - } - - Ok(items) - } - - let content; - - let _mod_token = input.parse()?; - let ident = input.parse()?; - let _brace_token = braced!(content in input); - let items = content.call(parse_items)?; - - Ok(Input { - _mod_token, - ident, - _brace_token, - items, - }) - } -} - -fn init_args(tokens: TokenStream2) -> parse::Result<InitArgs> { - (|input: ParseStream<'_>| -> parse::Result<InitArgs> { - if input.is_empty() { - return Ok(InitArgs::default()); - } - - let mut local_resources = None; - - let content; - parenthesized!(content in input); - - if !content.is_empty() { - loop { - // Parse identifier name - let ident: Ident = content.parse()?; - // Handle equal sign - let _: Token![=] = content.parse()?; - - match &*ident.to_string() { - "local" => { - if local_resources.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - local_resources = Some(util::parse_local_resources(&content)?); - } - _ => { - return Err(parse::Error::new(ident.span(), "unexpected argument")); - } - } - - if content.is_empty() { - break; - } - // Handle comma: , - let _: Token![,] = content.parse()?; - } - } - - if let Some(locals) = &local_resources { - for (ident, task_local) in locals { - if let TaskLocal::External = task_local { - return Err(parse::Error::new( - ident.span(), - "only declared local resources are allowed in init", - )); - } - } - } - - Ok(InitArgs { - local_resources: local_resources.unwrap_or_default(), - }) - }) - .parse2(tokens) -} - -fn idle_args(tokens: TokenStream2) -> parse::Result<IdleArgs> { - (|input: ParseStream<'_>| -> parse::Result<IdleArgs> { - if input.is_empty() { - return Ok(IdleArgs::default()); - } - - let mut shared_resources = None; - let mut local_resources = None; - - let content; - parenthesized!(content in input); - if !content.is_empty() { - loop { - // Parse identifier name - let ident: Ident = content.parse()?; - // Handle equal sign - let _: Token![=] = content.parse()?; - - match &*ident.to_string() { - "shared" => { - if shared_resources.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - shared_resources = Some(util::parse_shared_resources(&content)?); - } - - "local" => { - if local_resources.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - local_resources = Some(util::parse_local_resources(&content)?); - } - - _ => { - return Err(parse::Error::new(ident.span(), "unexpected argument")); - } - } - if content.is_empty() { - break; - } - - // Handle comma: , - let _: Token![,] = content.parse()?; - } - } - - Ok(IdleArgs { - shared_resources: shared_resources.unwrap_or_default(), - local_resources: local_resources.unwrap_or_default(), - }) - }) - .parse2(tokens) -} - -fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, SoftwareTaskArgs>> { - (|input: ParseStream<'_>| -> parse::Result<Either<HardwareTaskArgs, SoftwareTaskArgs>> { - if input.is_empty() { - return Ok(Either::Right(SoftwareTaskArgs::default())); - } - - let mut binds = None; - let mut capacity = None; - let mut priority = None; - let mut shared_resources = None; - let mut local_resources = None; - let mut prio_span = None; - - let content; - parenthesized!(content in input); - loop { - if content.is_empty() { - break; - } - - // Parse identifier name - let ident: Ident = content.parse()?; - let ident_s = ident.to_string(); - - // Handle equal sign - let _: Token![=] = content.parse()?; - - match &*ident_s { - "binds" => { - if binds.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - if capacity.is_some() { - return Err(parse::Error::new( - ident.span(), - "hardware tasks can't use the `capacity` argument", - )); - } - - // Parse identifier name - let ident = content.parse()?; - - binds = Some(ident); - } - - "capacity" => { - if capacity.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - if binds.is_some() { - return Err(parse::Error::new( - ident.span(), - "hardware tasks can't use the `capacity` argument", - )); - } - - // #lit - let lit: LitInt = content.parse()?; - - if !lit.suffix().is_empty() { - return Err(parse::Error::new( - lit.span(), - "this literal must be unsuffixed", - )); - } - - let value = lit.base10_parse::<u8>().ok(); - if value.is_none() || value == Some(0) { - return Err(parse::Error::new( - lit.span(), - "this literal must be in the range 1...255", - )); - } - - capacity = Some(value.unwrap()); - } - - "priority" => { - if priority.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - // #lit - let lit: LitInt = content.parse()?; - - if !lit.suffix().is_empty() { - return Err(parse::Error::new( - lit.span(), - "this literal must be unsuffixed", - )); - } - - let value = lit.base10_parse::<u8>().ok(); - if value.is_none() { - return Err(parse::Error::new( - lit.span(), - "this literal must be in the range 0...255", - )); - } - - prio_span = Some(lit.span()); - priority = Some(value.unwrap()); - } - - "shared" => { - if shared_resources.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - shared_resources = Some(util::parse_shared_resources(&content)?); - } - - "local" => { - if local_resources.is_some() { - return Err(parse::Error::new( - ident.span(), - "argument appears more than once", - )); - } - - local_resources = Some(util::parse_local_resources(&content)?); - } - - _ => { - return Err(parse::Error::new(ident.span(), "unexpected argument")); - } - } - - if content.is_empty() { - break; - } - - // Handle comma: , - let _: Token![,] = content.parse()?; - } - let priority = priority.unwrap_or(1); - let shared_resources = shared_resources.unwrap_or_default(); - let local_resources = local_resources.unwrap_or_default(); - - Ok(if let Some(binds) = binds { - if priority == 0 { - return Err(parse::Error::new( - prio_span.unwrap(), - "hardware tasks are not allowed to be at priority 0", - )); - } - - Either::Left(HardwareTaskArgs { - binds, - priority, - shared_resources, - local_resources, - }) - } else { - Either::Right(SoftwareTaskArgs { - priority, - shared_resources, - local_resources, - }) - }) - }) - .parse2(tokens) -} |