use crate::ast::BlockHeader;
use crate::kw;
use syn::parse::{Parse, ParseStream};
use syn::token::{Brace, Colon, Eq, Semi};
use syn::{Expr, Ident, Type, braced};
#[allow(dead_code)]
pub struct ConfigAst {
pub header: BlockHeader<kw::config>,
pub brace_token: Brace,
pub params: Option<ParamConfigBlock>,
pub eos: Option<Semi>,
}
#[allow(dead_code)]
pub struct ParamConfigBlock {
pub key: BlockHeader<kw::hyperparams>,
pub brace_token: Brace,
pub contents: Vec<ParamConfigStmt>,
pub eos: Option<Semi>,
}
#[allow(dead_code)]
pub struct ParamConfigStmt {
pub key: Ident,
pub colon_token: Colon,
pub typed: Type,
pub value: Option<ValueExpr>,
pub eos: Semi,
}
#[allow(dead_code)]
pub struct ValueExpr {
pub eq_token: Eq,
pub value: Expr,
}
impl Parse for ValueExpr {
fn parse(input: ParseStream) -> syn::Result<Self> {
let eq_token = input.parse::<Eq>()?;
let value = input.parse::<Expr>()?;
Ok(ValueExpr { eq_token, value })
}
}
impl Parse for ParamConfigStmt {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key = input.parse::<Ident>()?;
let colon_token = input.parse::<Colon>()?;
let typed = input.parse::<Type>()?;
let value = input.parse::<ValueExpr>().ok();
let eos = input.parse::<Semi>()?;
Ok(ParamConfigStmt {
key,
colon_token,
typed,
value,
eos,
})
}
}
impl Parse for ParamConfigBlock {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key = input.parse::<BlockHeader<kw::hyperparams>>()?;
let mut contents = Vec::new();
let content; let brace_token = braced!(content in input); while !content.is_empty() {
let stmt: ParamConfigStmt = content.parse()?;
contents.push(stmt);
}
let eos = if content.peek(Semi) {
Some(content.parse::<Semi>()?)
} else {
None
};
Ok(ParamConfigBlock {
key,
brace_token,
contents,
eos,
})
}
}
impl Parse for ConfigAst {
fn parse(input: ParseStream) -> syn::Result<Self> {
let header = input.parse::<BlockHeader<kw::config>>()?;
let mut params = None;
let content; let brace_token = braced!(content in input);
while !content.is_empty() {
if content.peek(kw::hyperparams) {
params = Some(content.parse::<ParamConfigBlock>()?);
} else {
return Err(syn::Error::new(
content.span(),
"expected `hyperparams` block",
));
}
}
let eos = if content.peek(Semi) {
Some(content.parse::<Semi>()?)
} else {
None
};
Ok(ConfigAst {
header,
brace_token,
params,
eos,
})
}
}