/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! Parsing code for the ast use quote::format_ident; use syn::{ braced, parenthesized, parse::{Parse, ParseStream}, token, Attribute, Ident, Token, }; use super::ast::*; impl Parse for Node { fn parse(input: ParseStream) -> syn::Result { let attrs = input.parse()?; let vis = input.parse()?; let lookahead = input.lookahead1(); if lookahead.peek(Token![struct]) { let _: Token![struct] = input.parse()?; let ident = input.parse()?; let generics = input.parse()?; let fields: Fields = input.parse()?; if fields.not_named() { let _: Token![;] = input.parse()?; } let mut wraps_field = None; for f in fields.iter() { if f.attrs.wraps { if wraps_field.is_some() { return Err(syn::Error::new(f.var_name.span(), "Multiple wraps")); } else { wraps_field = Some(f.clone()); } } } let st = Struct { fields, wraps_field, }; Ok(Self { attrs, vis, ident, generics, def: NodeDef::Struct(st), }) } else if lookahead.peek(Token![enum]) { let _: Token![enum] = input.parse()?; let ident = input.parse()?; let generics = input.parse()?; let content; braced!(content in input); let variants = content.parse_terminated(Variant::parse, Token![,])?; Ok(Self { attrs, vis, ident, generics, def: NodeDef::Enum(variants.into_iter().collect()), }) } else { Err(lookahead.error()) } } } impl Parse for Attributes { fn parse(input: ParseStream) -> syn::Result { let parsed_attrs = input.call(Attribute::parse_outer)?; Self::from_list(&parsed_attrs) } } impl Attributes { pub fn from_list(attrs: &[Attribute]) -> syn::Result { let mut result = Attributes::default(); for attr in attrs { if attr.path().is_ident("node") { attr.parse_nested_meta(|meta| { if meta.path.is_ident("from") { let content; parenthesized!(content in meta.input); result.from = Some(content.parse()?); return Ok(()); } else if meta.path.is_ident("wraps") { result.wraps = true; return Ok(()); } Err(meta.error("unrecognized node attr")) })?; } } Ok(result) } } impl Parse for Fields { fn parse(input: ParseStream) -> syn::Result { let lookahead = input.lookahead1(); if lookahead.peek(Token![,]) || lookahead.peek(Token![;]) || lookahead.peek(Token![=]) { Ok(Self::Unit) } else if lookahead.peek(token::Brace) { let content; braced!(content in input); Ok(Self::Named( content .parse_terminated(Field::parse_named, Token![,])? .into_iter() .collect(), )) } else if lookahead.peek(token::Paren) { let content; parenthesized!(content in input); let mut counter = 0; let mut fields = vec![]; while !content.is_empty() { fields.push(Field::parse_unnamed(&content, counter)?); counter += 1; if content.is_empty() { break; } let _: Token![,] = content.parse()?; } Ok(Self::Unnamed(fields)) } else { Err(lookahead.error()) } } } impl Parse for Variant { fn parse(input: ParseStream) -> syn::Result { let attrs = input.parse()?; let vis = input.parse()?; let ident = input.parse()?; let fields = input.parse()?; let mut discriminant = None; if input.peek(Token![=]) { let _: Token![=] = input.parse()?; discriminant = Some(input.parse()?); } Ok(Self { attrs, vis, ident, fields, discriminant, }) } } impl Field { fn parse_named(input: ParseStream) -> syn::Result { let attrs = input.parse()?; let vis = input.parse()?; let ident: Ident = input.parse()?; let _ = input.parse::()?; let ty = input.parse()?; Ok(Self { attrs, vis, ident: Some(ident.clone()), ty, var_name: ident, }) } fn parse_unnamed(input: ParseStream, index: usize) -> syn::Result { Ok(Self { attrs: input.parse()?, vis: input.parse()?, ident: None, ty: input.parse()?, var_name: format_ident!("var{index}"), }) } }