use modality_lang::PropertySign;
fn main() -> Result<(), String> {
let content = std::fs::read_to_string("examples/models/SimpleExamples.modality")
.map_err(|e| format!("Failed to read file: {}", e))?;
let lines: Vec<&str> = content.lines()
.map(|line| line.trim())
.filter(|line| !line.is_empty() && !line.starts_with("//"))
.collect();
let mut i = 0;
let mut model_count = 0;
while i < lines.len() {
let line = lines[i];
if line.starts_with("model ") {
model_count += 1;
println!("\n=== Model {} ===", model_count);
let (model, new_i) = parse_single_model(&lines, i)?;
i = new_i;
println!("Model name: {}", model.name);
println!("Number of graphs: {}", model.graphs.len());
for (graph_idx, graph) in model.graphs.iter().enumerate() {
println!(" Graph {}: {}", graph_idx + 1, graph.name);
println!(" Transitions: {}", graph.transitions.len());
for transition in &graph.transitions {
print!(" {} --> {}:", transition.from, transition.to);
if transition.properties.is_empty() {
println!();
} else {
for prop in &transition.properties {
let sign = match prop.sign {
PropertySign::Plus => "+",
PropertySign::Minus => "-",
};
print!(" {}{}", sign, prop.name);
}
println!();
}
}
}
} else {
i += 1;
}
}
println!("\nTotal models found: {}", model_count);
Ok(())
}
fn parse_single_model(lines: &[&str], start: usize) -> Result<(modality_lang::Model, usize), String> {
if start >= lines.len() {
return Err("Unexpected end of file".to_string());
}
let model_line = lines[start];
let model_name = model_line
.strip_prefix("model ")
.and_then(|s| s.strip_suffix(':'))
.ok_or_else(|| format!("Invalid model declaration: {}", model_line))?;
let mut model = modality_lang::Model::new(model_name.to_string());
let mut i = start + 1;
while i < lines.len() {
let line = lines[i];
if line.starts_with("model ") {
break; }
if line.starts_with("graph ") {
let (graph, new_i) = parse_single_graph(lines, i)?;
model.add_graph(graph);
i = new_i;
} else {
i += 1; }
}
Ok((model, i))
}
fn parse_single_graph(lines: &[&str], start: usize) -> Result<(modality_lang::Graph, usize), String> {
if start >= lines.len() {
return Err("Unexpected end of file".to_string());
}
let graph_line = lines[start];
let graph_name = graph_line
.strip_prefix("graph ")
.and_then(|s| s.strip_suffix(':'))
.ok_or_else(|| format!("Invalid graph declaration: {}", graph_line))?;
let mut graph = modality_lang::Graph::new(graph_name.to_string());
let mut i = start + 1;
while i < lines.len() {
let line = lines[i];
if line.starts_with("model ") || line.starts_with("graph ") {
break; }
if line.contains("-->") {
let transition = parse_single_transition(line)?;
graph.add_transition(transition);
}
i += 1;
}
Ok((graph, i))
}
fn parse_single_transition(line: &str) -> Result<modality_lang::Transition, String> {
let parts: Vec<&str> = line.split("-->").collect();
if parts.len() != 2 {
return Err(format!("Invalid transition format: {}", line));
}
let from = parts[0].trim();
let to_and_props = parts[1].trim();
if to_and_props.contains(':') {
let colon_parts: Vec<&str> = to_and_props.split(':').collect();
if colon_parts.len() != 2 {
return Err(format!("Invalid transition format (invalid colon): {}", line));
}
let to = colon_parts[0].trim();
let props_str = colon_parts[1].trim();
let mut transition = modality_lang::Transition::new(from.to_string(), to.to_string());
if !props_str.is_empty() {
let properties = parse_single_properties(props_str)?;
for prop in properties {
transition.add_property(prop);
}
}
Ok(transition)
} else {
let to = to_and_props;
Ok(modality_lang::Transition::new(from.to_string(), to.to_string()))
}
}
fn parse_single_properties(props_str: &str) -> Result<Vec<modality_lang::Property>, String> {
let mut properties = Vec::new();
for prop_str in props_str.split_whitespace() {
let prop = parse_single_property(prop_str)?;
properties.push(prop);
}
Ok(properties)
}
fn parse_single_property(prop_str: &str) -> Result<modality_lang::Property, String> {
if prop_str.is_empty() {
return Err("Empty property".to_string());
}
let sign = match prop_str.chars().next() {
Some('+') => modality_lang::PropertySign::Plus,
Some('-') => modality_lang::PropertySign::Minus,
_ => return Err(format!("Invalid property sign in: {}", prop_str)),
};
let name = prop_str[1..].to_string();
if name.is_empty() {
return Err(format!("Property name is empty: {}", prop_str));
}
Ok(modality_lang::Property::new(sign, name))
}