openinfer-dsl 0.1.3

Rust-embedded DSL for defining OpenInfer graphs with explicit control flow and memory semantics.
Documentation
use syn::parse::{ParseStream, Result};
use syn::{Ident, LitInt, Token};

use crate::types::{Dim, DimAtom};

pub(crate) fn parse_dims(input: ParseStream) -> Result<Vec<Dim>> {
    let mut dims = Vec::new();
    if input.peek(syn::token::Bracket) {
        let content;
        syn::bracketed!(content in input);
        while !content.is_empty() {
            if content.peek(LitInt) {
                let lit: LitInt = content.parse()?;
                if content.peek(Token![*]) {
                    content.parse::<Token![*]>()?;
                    let right = parse_dim_atom(&content)?;
                    dims.push(Dim::Mul {
                        left: DimAtom::Lit(lit),
                        right,
                    });
                } else {
                    dims.push(Dim::Lit(lit));
                }
            } else {
                let ident: Ident = content.parse()?;
                if content.peek(Token![*]) {
                    content.parse::<Token![*]>()?;
                    let right = parse_dim_atom(&content)?;
                    dims.push(Dim::Mul {
                        left: DimAtom::Ident(ident),
                        right,
                    });
                } else {
                    dims.push(Dim::Ident(ident));
                }
            }
            if content.peek(Token![,]) {
                content.parse::<Token![,]>()?;
            }
        }
    }
    Ok(dims)
}

fn parse_dim_atom(input: ParseStream) -> Result<DimAtom> {
    if input.peek(LitInt) {
        Ok(DimAtom::Lit(input.parse()?))
    } else if input.peek(Ident) {
        Ok(DimAtom::Ident(input.parse()?))
    } else {
        Err(input.error("expected identifier or integer for dimension expression"))
    }
}