asdl 1.0.1

Parser for ASDL format. Describes the abstract syntax of compiler intermediate representations and other tree-like data structures
Documentation
use crate::model::*;
use crate::ast;
use crate::util::FieldNames;

impl Asdl {
    pub(crate) fn new(root: &ast::Root) -> Self {
        Asdl { types: root.types.iter().map(ty).collect(), comments: comments(&root.comments) }
    }
}

fn ty(ty: &ast::Type) -> Type {
    match ty {
        ast::Type::SumType(sty) => sum_type(sty).into(),
        ast::Type::ProdType(pty) => prod_type(pty).into(),
    }
}

impl SumType {
    fn new(
        id: String,
        constructors: Vec<Constructor>,
        attributes: Vec<Field>,
        comments: Vec<String>,
    ) -> Self {
        SumType { id, constructors, attributes, comments }
    }
}

fn sum_type(ty: &ast::SumType) -> SumType {
    let id = ty.type_id.to_string();
    let constructors = ty.constructors.iter().map(constr).collect();
    let attributes = ty.attrs.as_ref().map(|a| fields(&a.fields)).unwrap_or_default();
    SumType::new(id, constructors, attributes, comments(&ty.comments))
}

impl Constructor {
    fn new(id: String, fields: Vec<Field>, comments: Vec<String>) -> Self {
        Constructor { id, fields, comments }
    }
}

fn constr(c: &ast::Constr) -> Constructor {
    Constructor::new(c.id.to_string(), fields(&c.fields), comments(&c.comments))
}

impl ProdType {
    fn new(id: String, fields: Vec<Field>, comments: Vec<String>) -> Self {
        ProdType { id, fields, comments }
    }
}

fn prod_type(ty: &ast::ProdType) -> ProdType {
    ProdType::new(ty.type_id.to_string(), fields(&ty.fields), comments(&ty.comments))
}

fn comments(comments: &Vec<&str>) -> Vec<String> {
    comments.iter().map(ToString::to_string).collect()
}

fn fields(fields: &Vec<ast::Field>) -> Vec<Field> {
    let mut names = FieldNames::default();
    fields.iter().map(|f| field(f, &mut names)).collect()
}

impl Field {
    fn required(id: String, type_id: String) -> Self {
        Field { id, type_id, arity: Arity::Required }
    }

    fn optional(id: String, type_id: String) -> Self {
        Field { id, type_id, arity: Arity::Optional }
    }

    fn repeated(id: String, type_id: String) -> Self {
        Field { id, type_id, arity: Arity::Repeated }
    }
}

fn field(f: &ast::Field, names: &mut FieldNames) -> Field {
    match f {
        ast::Field::Required(f) => {
            Field::required(names.get_or_generate(&f.id, &f.type_id), f.type_id.to_string())
        }
        ast::Field::Optional(f) => {
            Field::optional(names.get_or_generate(&f.id, &f.type_id), f.type_id.to_string())
        }
        ast::Field::Repeated(f) => {
            Field::repeated(names.get_or_generate(&f.id, &f.type_id), f.type_id.to_string())
        }
    }
}