modality-lang 0.1.6

Modality language lib
Documentation
use crate::ast::{Model, Graph, Transition, Property, PropertySign, Formula, FormulaExpr, GraphState, TopLevelItem};

grammar;

pub TopLevel: Vec<Model> = {
    <items:TopLevelItem*> => {
        let mut models = Vec::new();
        for item in items {
            if let TopLevelItem::Model(model) = item {
                models.push(model);
            }
        }
        models
    }
};

TopLevelItem: TopLevelItem = {
    <model:Model> => TopLevelItem::Model(model),
    <formula:Formula> => TopLevelItem::Formula(formula)
};

pub Model: Model = {
    <model:ModelDecl> => model
};

ModelDecl: Model = {
    "model" <name:Ident> ":" <graphs:Graph*> => {
        let mut model = Model::new(name);
        for graph in graphs {
            model.add_graph(graph);
        }
        model
    }
};

Graph: Graph = {
    "graph" <name:Ident> ":" <transitions:Transition*> => {
        let mut graph = Graph::new(name);
        for transition in transitions {
            graph.add_transition(transition);
        }
        graph
    }
};

Transition: Transition = {
    <from:Ident> "-->" <to:Ident> => {
        Transition::new(from, to)
    },
    <from:Ident> "-->" <to:Ident> ":" <properties:PropertyList> => {
        let mut transition = Transition::new(from, to);
        for property in properties {
            transition.add_property(property);
        }
        transition
    }
};

PropertyList: Vec<Property> = {
    <property:Property> => vec![property],
    <properties:PropertyList> <property:Property> => {
        let mut props = properties;
        props.push(property);
        props
    }
};

Property: Property = {
    "+" <name:Ident> => Property::new(PropertySign::Plus, name),
    "-" <name:Ident> => Property::new(PropertySign::Minus, name)
};

// Formula parsing
pub Formula: Formula = {
    <formula:FormulaDecl> => formula
};

FormulaDecl: Formula = {
    "formula" <name:Ident> ":" <expr:FormulaExpr> => {
        Formula::new(name, expr)
    }
};

FormulaExpr: FormulaExpr = {
    <expr:FormulaOrExpr> => expr
};

FormulaOrExpr: FormulaExpr = {
    <expr:FormulaAndExpr> => expr,
    <expr:FormulaOrExpr> "or" <expr2:FormulaAndExpr> => {
        FormulaExpr::Or(Box::new(expr), Box::new(expr2))
    }
};

FormulaAndExpr: FormulaExpr = {
    <expr:FormulaAtom> => expr,
    <expr:FormulaAndExpr> "and" <expr2:FormulaAtom> => {
        FormulaExpr::And(Box::new(expr), Box::new(expr2))
    }
};

FormulaAtom: FormulaExpr = {
    "true" => FormulaExpr::True,
    "false" => FormulaExpr::False,
    "(" <expr:FormulaExpr> ")" => {
        FormulaExpr::Paren(Box::new(expr))
    },
    "<" <properties:PropertyList> ">" <expr:FormulaAtom> => {
        FormulaExpr::Diamond(properties, Box::new(expr))
    },
    "[" <properties:PropertyList> "]" <expr:FormulaAtom> => {
        FormulaExpr::Box(properties, Box::new(expr))
    }
};

Ident: String = {
    r#"[a-zA-Z_][a-zA-Z0-9_]*"# => <>.to_string()
};