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()
};