blob: 4bb2ae2ac10124267477615cc4c755cbdedf841b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2021 CentraleSupelec, CEA-LIST
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Erwan Mahé (CentraleSupelec) - initial API and implementation
*******************************************************************************/
use std::fs;
use std::collections::{HashSet,HashMap};
use std::collections::btree_map::BTreeMap;
use std::path::Path;
use pest::iterators::Pair;
use crate::pest::Parser;
use crate::core::syntax::interaction::Interaction;
use crate::core::syntax::action::*;
use crate::core::context::general::GeneralContext;
use crate::from_text::error::HibouParsingError;
use crate::process::log::ProcessLogger;
use crate::from_text::parser::*;
use crate::rendering::process::graphic_logger::*;
use crate::process::hibou_process::*;
use crate::process::verdicts::GlobalVerdict;
use crate::process::process_manager::ProcessPriorities;
use crate::from_text::hsf_file::ProcessKind;
pub struct HibouOptions {
pub loggers : Vec<Box<dyn ProcessLogger>>,
pub strategy : HibouSearchStrategy,
pub pre_filters : Vec<HibouPreFilter>,
pub temporality : HibouProcessTemporality,
pub goal : Option<GlobalVerdict>,
pub frontier_priorities : ProcessPriorities
}
impl HibouOptions {
pub fn new(loggers : Vec<Box<dyn ProcessLogger>>,
strategy : HibouSearchStrategy,
pre_filters : Vec<HibouPreFilter>,
temporality : HibouProcessTemporality,
goal:Option<GlobalVerdict>,
frontier_priorities : ProcessPriorities) -> HibouOptions {
return HibouOptions{loggers,strategy,pre_filters,temporality,goal,frontier_priorities};
}
pub fn default_explore() -> HibouOptions {
return HibouOptions{loggers:Vec::new(),
strategy:HibouSearchStrategy::BFS,
pre_filters:vec![HibouPreFilter::MaxLoopInstanciation(1)],
temporality:HibouProcessTemporality::UnTimed,
goal:None,
frontier_priorities:ProcessPriorities::new(0,0,0)};
}
pub fn default_analyze() -> HibouOptions {
return HibouOptions{loggers:Vec::new(),
strategy:HibouSearchStrategy::BFS,
pre_filters:Vec::new(),
temporality:HibouProcessTemporality::UnTimed,
goal:Some(GlobalVerdict::Pass),
frontier_priorities:ProcessPriorities::new(0,0,0)};
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
enum LoggerKinds {
graphic
}
pub fn parse_hibou_options(option_pair : Pair<Rule>,
file_name : &str,
process_kind : &ProcessKind) -> Result<HibouOptions,HibouParsingError> {
let mut loggers : Vec<Box<dyn ProcessLogger>> = Vec::new();
let mut strategy : HibouSearchStrategy = HibouSearchStrategy::BFS;
let mut frontier_priorities = ProcessPriorities::new(0,0,0);
let mut pre_filters : Vec<HibouPreFilter> = Vec::new();
let mut temporality : HibouProcessTemporality = HibouProcessTemporality::UnTimed;
let mut goal : Option<GlobalVerdict> = None;
// ***
let mut got_loggers : bool = false;
let mut got_strategy : bool = false;
let mut got_frontier_priorities : bool = false;
let mut got_pre_filters : bool = false;
let mut got_temporality : bool = false;
let mut got_goal : bool = false;
// ***
let mut declared_loggers : HashSet<LoggerKinds> = HashSet::new();
// ***
for option_decl_pair in option_pair.into_inner() {
match option_decl_pair.as_rule() {
Rule::OPTION_TEMPORALITY_TIMED => {
if got_temporality {
return Err( HibouParsingError::HsfSetupError("several 'temporality=[X]' declared in the same '@X_option' section".to_string()));
}
got_temporality = true;
temporality = HibouProcessTemporality::Timed;
},
Rule::OPTION_TEMPORALITY_UNTIMED => {
if got_temporality {
return Err( HibouParsingError::HsfSetupError("several 'temporality=[X]' declared in the same '@X_option' section".to_string()));
}
got_temporality = true;
temporality = HibouProcessTemporality::UnTimed;
},
Rule::OPTION_LOGGER_DECL => {
if got_loggers {
return Err( HibouParsingError::HsfSetupError("several 'loggers=[X]' declared in the same '@X_option' section".to_string()));
}
got_loggers = true;
// ***
for logger_kind_pair in option_decl_pair.into_inner() {
match logger_kind_pair.as_rule() {
Rule::OPTION_GRAPHIC_LOGGER => {
if declared_loggers.contains(&LoggerKinds::graphic) {
return Err( HibouParsingError::HsfSetupError("several 'graphic' loggers declared in the same '@X_option' section".to_string()));
}
declared_loggers.insert( LoggerKinds::graphic );
let graphic_logger_pair = logger_kind_pair.into_inner().next();
match graphic_logger_pair {
None => {
loggers.push(Box::new(GraphicProcessLogger::new(file_name.to_string(),GraphicProcessLoggerKind::png ) ) );
},
Some(graphic_logger_kind_pair) => {
match graphic_logger_kind_pair.as_rule() {
Rule::GRAPHIC_LOGGER_KIND_png => {
loggers.push(Box::new(GraphicProcessLogger::new(file_name.to_string(),GraphicProcessLoggerKind::png ) ) );
},
Rule::GRAPHIC_LOGGER_KIND_svg => {
loggers.push(Box::new(GraphicProcessLogger::new(file_name.to_string(),GraphicProcessLoggerKind::svg ) ) );
},
_ => {
panic!("what rule then ? : {:?}", graphic_logger_kind_pair.as_rule() );
}
}
}
}
},
_ => {
panic!("what rule then ? : {:?}", logger_kind_pair.as_rule() );
}
}
}
},
Rule::OPTION_STRATEGY_DECL => {
if got_strategy {
return Err( HibouParsingError::HsfSetupError("several 'strategy=X' declared in the same '@X_option' section".to_string()));
}
got_strategy = true;
// ***
let strategy_pair = option_decl_pair.into_inner().next().unwrap();
match strategy_pair.as_rule() {
Rule::OPTION_STRATEGY_BFS => {
strategy = HibouSearchStrategy::BFS;
},
Rule::OPTION_STRATEGY_DFS => {
strategy = HibouSearchStrategy::DFS;
},
_ => {
panic!("what rule then ? : {:?}", strategy_pair.as_rule() );
}
}
},
Rule::OPTION_PRIORITIES_DECL => {
if got_frontier_priorities {
return Err( HibouParsingError::HsfSetupError("several 'frontier_priorities=X' declared in the same '@X_option' section".to_string()));
}
got_frontier_priorities = true;
// ***
for priority_pair in option_decl_pair.into_inner() {
let mut priority_contents = priority_pair.into_inner();
let priority_kind_pair = priority_contents.next().unwrap();
// ***
let priority_level_pair = priority_contents.next().unwrap();
let priority_level_str : String = priority_level_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
let priority_level : i32 = priority_level_str.parse::<i32>().unwrap();
// ***
match priority_kind_pair.as_rule() {
Rule::OPTION_PRIORITTY_emission => {
frontier_priorities.emission = priority_level;
},
Rule::OPTION_PRIORITTY_reception => {
frontier_priorities.reception = priority_level;
},
Rule::OPTION_PRIORITY_loop => {
frontier_priorities.in_loop = priority_level;
},
_ => {
panic!("what rule then ? : {:?}", priority_kind_pair.as_rule() );
}
}
}
},
Rule::OPTION_PREFILTERS_DECL => {
if got_pre_filters {
return Err( HibouParsingError::HsfSetupError("several 'pre_filters=[X]' declared in the same '@X_option' section".to_string()));
}
got_pre_filters = true;
// ***
for pre_filter_pair in option_decl_pair.into_inner() {
match pre_filter_pair.as_rule() {
Rule::OPTION_PREFILTER_MAX_DEPTH => {
let content = pre_filter_pair.into_inner().next().unwrap();
let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
let my_val : u32 = content_str.parse::<u32>().unwrap();
pre_filters.push(HibouPreFilter::MaxProcessDepth(my_val));
},
Rule::OPTION_PREFILTER_MAX_LOOP_DEPTH => {
let content = pre_filter_pair.into_inner().next().unwrap();
let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
let my_val : u32 = content_str.parse::<u32>().unwrap();
pre_filters.push(HibouPreFilter::MaxLoopInstanciation(my_val));
},
Rule::OPTION_PREFILTER_MAX_NODE_NUMBER => {
let content = pre_filter_pair.into_inner().next().unwrap();
let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
let my_val : u32 = content_str.parse::<u32>().unwrap();
pre_filters.push(HibouPreFilter::MaxNodeNumber(my_val));
},
_ => {
panic!("what rule then ? : {:?}", pre_filter_pair.as_rule() );
}
}
}
},
Rule::OPTION_GOAL_DECL => {
if got_goal {
return Err( HibouParsingError::HsfSetupError("several 'goal=X' declared in the same '@X_option' section".to_string()));
}
got_goal = true;
// ***
let goal_pair = option_decl_pair.into_inner().next().unwrap();
match goal_pair.as_rule() {
Rule::OPTION_GOAL_pass => {
goal = Some( GlobalVerdict::Pass );
},
Rule::OPTION_GOAL_weakpass => {
goal = Some( GlobalVerdict::WeakPass );
},
_ => {
panic!("what rule then ? : {:?}", goal_pair.as_rule() );
}
}
},
_ => {
panic!("what rule then ? : {:?}", option_decl_pair.as_rule() );
}
}
}
match process_kind {
ProcessKind::Analyze => {
let ana_goal : GlobalVerdict;
match goal {
None => {
ana_goal = GlobalVerdict::Pass;
},
Some( goal_in ) => {
ana_goal = goal_in;
}
}
// ***
return Ok( HibouOptions::new(loggers,strategy,pre_filters,temporality, Some(ana_goal),frontier_priorities) );
},
_ => {
return Ok( HibouOptions::new(loggers,strategy,pre_filters,temporality, None,frontier_priorities) );
}
}
}