-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/reading graph #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
a577144
3081790
8eca4bb
44d8903
ec321a6
74a5b1f
cca478f
3173320
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,15 @@ | ||
| use log::info; | ||
| use std::collections::{BTreeMap, BTreeSet}; | ||
| use serde::{Serialize, Deserialize}; | ||
|
|
||
|
|
||
| use crate::automata::regular_expression as RE; | ||
| use crate::display::DisplayGraph; | ||
| use crate::utils::Graph; | ||
| use crate::utils::{Graph, IntoGraph}; | ||
|
|
||
| mod string_transform; | ||
|
|
||
| #[derive(Debug)] | ||
| #[derive(Debug, Serialize, Deserialize)] | ||
| pub struct NFA { | ||
| start_state: usize, | ||
| num_states: usize, | ||
|
|
@@ -213,8 +217,8 @@ impl From<&RE::ReOperator> for NFA { | |
| } | ||
| } | ||
|
|
||
| impl Into<Graph> for NFA { | ||
| fn into(self) -> Graph { | ||
| impl IntoGraph for NFA { | ||
| fn into_graph(&self) -> Graph { | ||
| let mut graph = Graph::new(); | ||
|
|
||
| let finals_nodes = self | ||
|
|
@@ -264,6 +268,7 @@ mod test { | |
| Box::new(RE::ReOperator::Char('b')), | ||
| ); | ||
| let nfa = NFA::from(®ex); | ||
| println!("{:?}", nfa); | ||
| let out = serde_json::to_string(&nfa); | ||
| panic!("{:?}\n", out.unwrap()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. questo test utile per debuggare, però dovresti fixarlo.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,185 @@ | ||
| use std::collections::BTreeMap; | ||
|
|
||
| use super::NFA; | ||
|
|
||
| //TODO rifare tutto con strade | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. è ancora utile questo commento?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nop |
||
| use nom::{ | ||
| bytes::complete::take, | ||
| bytes::complete::take_while1, | ||
| bytes::streaming::tag, | ||
| character::complete::{char, one_of}, | ||
| character::complete::{digit1, multispace0}, | ||
| combinator::{map_res, opt}, | ||
| multi::separated_list0, | ||
| sequence::{delimited, preceded, tuple}, | ||
| IResult, | ||
| }; | ||
|
|
||
| const START_STATE_LABEL:&str= "start_state"; | ||
| const NUM_STATE_LABEL:&str= "num_states"; | ||
| const END_STATES_LABEL:&str= "end_states"; | ||
| const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; | ||
|
|
||
|
|
||
|
|
||
| fn read_num(input: &str) -> IResult<&str, usize> { | ||
| map_res(digit1, |digit_str: &str| digit_str.parse::<usize>())(input) | ||
| } | ||
|
|
||
| fn custom_label<'a>( | ||
| label: &str, | ||
| ) -> impl Fn(&'a str) -> IResult<&'a str, (&'a str, &'a str, &'a str, &'a str, &'a str)> + '_ { | ||
| move |input| tuple((multispace0, tag(label), multispace0, tag(":"), multispace0))(input) | ||
| } | ||
|
|
||
| fn read_start_stete(input: &str) -> IResult<&str, usize> { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo |
||
| preceded(custom_label(START_STATE_LABEL), read_num)(input) | ||
| } | ||
| fn read_num_states(input: &str) -> IResult<&str, usize> { | ||
| preceded(custom_label(NUM_STATE_LABEL), read_num)(input) | ||
| } | ||
|
|
||
|
|
||
| fn read_char(input: &str) -> IResult<&str, char> { | ||
| preceded( | ||
| multispace0, | ||
| delimited(char('\''), one_of(ALPHABET), char('\'')), | ||
| )(input) | ||
| } | ||
|
|
||
| fn read_num_array(input: &str) -> IResult<&str, Vec<usize>> { | ||
| delimited( | ||
| tag("["), | ||
| separated_list0(tag(","), delimited(multispace0, read_num, multispace0)), | ||
| tag("]"), | ||
| )(input) | ||
| } | ||
|
|
||
| fn read_finish_states(input: &str) -> IResult<&str, Vec<usize>> { | ||
| preceded(custom_label(END_STATES_LABEL), read_num_array)(input) | ||
| } | ||
|
|
||
| fn read_transiction(input: &str) -> IResult<&str, (usize, usize, char)> { | ||
| let (input, from) = delimited(multispace0, read_num, multispace0)(input)?; | ||
| let (input, _) = tag("--")(input)?; | ||
| let (input, ch) = opt(read_char)(input)?; | ||
| let (input, _) = preceded(multispace0, tag("-->"))(input)?; | ||
| let (input, to) = preceded(multispace0, read_num)(input)?; | ||
|
|
||
| Ok((input, (from, to, ch.unwrap_or('ε')))) | ||
| } | ||
|
|
||
| fn read_all_transictions(input: &str) -> IResult<&str, Vec<(usize, usize, char)>> { | ||
| separated_list0(multispace0, read_transiction)(input) | ||
| } | ||
|
|
||
|
|
||
| impl TryFrom<&str> for NFA { | ||
| // TODO: maybe we can change it | ||
| type Error = String; | ||
|
|
||
| fn try_from(value: &str) -> Result<Self, Self::Error> { | ||
| let out = tuple(( | ||
| read_start_stete, | ||
| read_finish_states, | ||
| read_num_states, | ||
| read_all_transictions, | ||
| ))(value); | ||
|
|
||
| match out { | ||
| Ok((_, (start_state, end_states, num_states, all_transitions))) => { | ||
| let mut transitions: Vec<BTreeMap<char, Vec<usize>>> = | ||
| (0..num_states).map(|_| BTreeMap::new()).collect(); | ||
| for (from, to, ch) in all_transitions.into_iter() { | ||
| if from >= num_states { | ||
| return Err(String::from("from out of num_state")); | ||
| } else if to >= num_states { | ||
| return Err(String::from("to out of num_state")); | ||
| } else { | ||
| transitions[from] | ||
| .entry(ch) | ||
| .and_modify(|x| x.push(to)) | ||
| .or_insert(vec![to]); | ||
| } | ||
| } | ||
| Ok(Self { | ||
| start_state, | ||
| num_states, | ||
| end_states, | ||
| transitions, | ||
| used_alphabet: ALPHABET.chars().collect(), | ||
| }) | ||
| } | ||
| Err(e) => Err(e.to_string()), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod test { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn string_to_nfa() { | ||
| //todo | ||
| if let Ok(_) = NFA::try_from(concat!( | ||
| "start_state: 0\n", | ||
| "finish_states: [ 2 ]\n", | ||
| " num_states: 5\n", | ||
| "0 --'b'--> 1\n", | ||
| "1 ----> 2\n", | ||
| "1 ----> 3\n", | ||
| "3 -- 'a' --> 4\n", | ||
| "4 ----> 3\n", | ||
| "4 ----> 2\n" | ||
| )) { | ||
| } else { | ||
| assert!(false); | ||
| } | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_edge() { | ||
| assert_eq!(read_transiction(" 1 ----> 3"), Ok(("", (1, 3, 'ε')))); | ||
| assert_eq!(read_transiction(" 2 -- 'a'--> 3"), Ok(("", (2, 3, 'a')))); | ||
| assert_eq!(read_transiction(" 2-- 'a' --> 3 "), Ok((" ", (2, 3, 'a')))); | ||
| assert_eq!(read_transiction("2 ----> 3"), Ok(("", (2, 3, 'ε')))); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_start_state() { | ||
| assert_eq!(read_start_stete("start_state : 100\n"), Ok(("\n", 100))); | ||
| } | ||
| #[test] | ||
| fn test_number_list() { | ||
| assert_eq!( | ||
| read_num_array("[ 10, 20 , 30 ]"), | ||
| Ok(("", vec![10, 20, 30])) | ||
| ); | ||
| } | ||
| #[test] | ||
| fn test_number() { | ||
| assert_eq!(read_num("10"), Ok(("", 10))); | ||
| assert_eq!(read_num("1234"), Ok(("", 1234))); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_label() { | ||
| assert_eq!( | ||
| custom_label("start_state")("start_state : 20"), | ||
| Ok(("20", ("", "start_state", " ", ":", " "))) | ||
| ); | ||
| assert_eq!( | ||
| custom_label("start_state")(" start_state: 30"), | ||
| Ok(("30", (" ", "start_state", "", ":", " "))) | ||
| ); | ||
| assert_eq!( | ||
| custom_label("start_state")("start_state : 10"), | ||
| Ok(("10", ("", "start_state", " ", ":", " "))) | ||
| ); | ||
| assert_eq!( | ||
| custom_label("start_state")("start_state :10"), | ||
| Ok(("10", ("", "start_state", " ", ":", ""))) | ||
| ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In rust ci sono dei trait
FromeIntoche sono builtin, non sarebbe meglio utilizzare quelli?https://doc.rust-lang.org/std/convert/trait.From.html
Poi se implementi from hai già into. Però alla fine è solo questione di stile quindi come vuoi 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Into non puoi passare l'oggetto come reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Puoi, ti basta implementare
Into<&Graph>.