Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ log = "0.4.17"
eframe = "0.19.0"
egui = "0.19.0"
wasm-bindgen = "0.2.83"
nom = "7.1.1"
serde = { version = "1.0.151", features = ["derive"] }
serde_yaml = "0.9.16"
serde_json = "1.0.91"
126 changes: 15 additions & 111 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,16 @@
use eframe::egui;
use egui::{emath, Color32, Frame, Pos2, Rect, RichText, Window};
use egui::{panel::TopBottomSide, CentralPanel, SidePanel, TopBottomPanel};

use crate::automata::DFA;
use crate::automata::NFA;
use crate::automata::ReOperator;
use crate::display::DisplayGraphParameter;
use crate::display::Visualizer;
use crate::utils::Graph;
use crate::display::RegularGui;

pub struct EguiApp {
error: Option<String>,
regex_text: String,

// This is indexed accordingly
// 0: Regex
// 1: NFA
// 2: DFA
// 3: Minimized DFA
// a union structure would be useful for accessing the Visualizers
// with both indixes and names, but it's problematic how to do it
// in rust.
to_visualize: [Visualizer; 4],
regular_gui: RegularGui,
}

impl Default for EguiApp {
fn default() -> Self {
Self {
error: None,
regex_text: String::new(),

to_visualize: [
Visualizer::new("Regex Syntax Tree".to_string()),
Visualizer::new("NFA".to_string()),
Visualizer::new("DFA".to_string()),
Visualizer::new("Minimized DFA".to_string()),
],
regular_gui: RegularGui::new(),
}
}
}
Expand All @@ -43,93 +19,21 @@ impl EguiApp {
pub fn new(_cc: &eframe::CreationContext) -> Self {
Self::default()
}

pub fn get_converter(index: i32) -> impl Fn(ReOperator) -> Graph {
match index {
0 => |re: ReOperator| re.into(),
1 => |re: ReOperator| NFA::from(&re).into(),
2 => |re: ReOperator| DFA::from(&NFA::from(&re)).into(),
3 => |re: ReOperator| DFA::from(&NFA::from(&re)).get_minimized_dfa().into(),
_ => panic!("Invalid index"),
}
}
}

impl eframe::App for EguiApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::SidePanel::left("Main").show(ctx, |ui| {
for (index, visualizer) in self.to_visualize.iter_mut().enumerate() {
ui.heading(&visualizer.box_title);
if index == 0 {
ui.horizontal(|ui| {
ui.label("inserisci la regex");
ui.text_edit_singleline(&mut self.regex_text)
.on_hover_text("Enter a regular expression");
});
}
if ui
.button(format!("Generate {}", visualizer.box_title))
.clicked()
{
match ReOperator::from_string(&self.regex_text) {
Ok(re) => {
visualizer.set_graph(Self::get_converter(index as i32)(re).into());
self.error = None;
}

Err(e) => {
self.error = Some(e.to_string());
}
};
}

ui.collapsing(
format!("{} visualizer option", visualizer.box_title),
|ui| {
ui.add(
egui::Slider::new(&mut visualizer.padding_x, 10.0..=100.0)
.text("padding x"),
);
ui.add(
egui::Slider::new(&mut visualizer.padding_y, 10.0..=100.0)
.text("padding y"),
);
ui.add(
egui::Slider::new(&mut visualizer.size_node, 10.0..=100.0)
.text("node size"),
);
},
);
}
if let Some(err) = &self.error {
ui.label(RichText::new(err).color(Color32::RED));
}
SidePanel::left("Left").show(ctx, |ui| {
self.regular_gui.draw_left_panel(ui);
});
SidePanel::right("Right").show(ctx, |ui| {
self.regular_gui.draw_right_panel(ui);
});
TopBottomPanel::bottom("Visualizer").show(ctx, |ui| {
self.regular_gui.draw_bottom_panel(ui);
});
CentralPanel::default().show(ctx, |ui| {
self.regular_gui.center_panel(ui);
});
for visualizer in self.to_visualize.iter_mut() {
visualizer.check_open();
let syntaxTree = Window::new(format!("{}", visualizer.box_title));
let syntaxTree = syntaxTree.open(&mut visualizer.is_win_open);
let syntaxTree = syntaxTree.scroll2([true, true]);
syntaxTree.show(ctx, |ui| {
Frame::canvas(ui.style()).show(ui, |ui| {
if let Some(tree) = &mut visualizer.graph {
let scren_size = tree.position(DisplayGraphParameter {
padding_x: visualizer.padding_x,
padding_y: visualizer.padding_y,
node_size: visualizer.size_node,
});
let (mut response, painter) =
ui.allocate_painter(scren_size, egui::Sense::hover());

let to_screen = emath::RectTransform::from_to(
Rect::from_min_size(Pos2::ZERO, response.rect.size()),
response.rect,
);
tree.drag_nodes(to_screen, ui, &mut response);
tree.draw(&painter, to_screen, &ui);
}
})
});
}
}
}
25 changes: 15 additions & 10 deletions src/automata/dfa.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::collections::{BTreeMap, BTreeSet};

use crate::automata::NFA;
use crate::automata::regular_expression as RE;
use crate::utils::{Graph, IndEdge, IndNode};
use crate::automata::NFA;
use crate::utils::DisjointUnionFind;
use crate::utils::IntoGraph;
use crate::utils::{Graph, IndEdge, IndNode};

type NfaStates = BTreeSet<usize>;
pub type NfaStates = BTreeSet<usize>;

#[derive(Debug, Clone)]
pub struct DFA<T> {
Expand All @@ -22,7 +23,7 @@ pub struct DFA<T> {
const INVALID_STATE: i32 = -1;

impl<T> DFA<T> {
fn new() -> Self {
pub fn new() -> Self {
Self {
num_states: 0,
start_state: 0,
Expand Down Expand Up @@ -106,7 +107,7 @@ impl<T> DFA<T> {
new_transitions[*idx].insert(*transition_ch, *head_to_idx.get(&dest_head).unwrap());
}
}

// create new end states, these should be unique
let mut new_end_states = BTreeSet::new();
for end_state in self.end_states.iter() {
Expand All @@ -117,7 +118,9 @@ impl<T> DFA<T> {
Self {
num_states,

start_state: *head_to_idx.get(&unequal_sets.find(self.start_state)).unwrap(),
start_state: *head_to_idx
.get(&unequal_sets.find(self.start_state))
.unwrap(),
end_states: new_end_states.into_iter().collect(),
transitions: new_transitions,
alphabet: self.alphabet.clone(),
Expand Down Expand Up @@ -217,12 +220,14 @@ impl<T> DFA<T> {
fn add_state(dfa: &mut DFA<T>, states: T) -> usize {
dfa.transitions.push(BTreeMap::new());


if let Some(map) = &mut dfa.idx_to_data {
map.insert(dfa.num_states, states);
} else {
dfa.idx_to_data = Some(BTreeMap::new());
dfa.idx_to_data.as_mut().unwrap().insert(dfa.num_states, states);
dfa.idx_to_data
.as_mut()
.unwrap()
.insert(dfa.num_states, states);
}

dfa.num_states += 1;
Expand Down Expand Up @@ -276,8 +281,8 @@ impl From<&RE::ReOperator> for DFA<NfaStates> {
}
}

impl<T> Into<Graph> for DFA<T> {
fn into(self) -> Graph {
impl<T> IntoGraph for DFA<T> {
fn into_graph(&self) -> Graph {
let mut graph = Graph::new();
Comment on lines -279 to 286
Copy link
Collaborator

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 From e Into che 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 🤷‍♂️

Copy link
Owner Author

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

Copy link
Collaborator

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>.


let finals_nodes = self
Expand Down
19 changes: 11 additions & 8 deletions src/automata/nfa.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use log::info;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};

use crate::automata::regular_expression as RE;
use crate::display::DisplayGraph;
use crate::utils::Graph;

#[derive(Debug)]
use crate::utils::{Graph, IntoGraph};

mod string_transform;

#[derive(Debug, Serialize, Deserialize)]
pub struct NFA {
start_state: usize,
num_states: usize,
Expand All @@ -18,7 +20,7 @@ pub struct NFA {
}

impl NFA {
fn new() -> Self {
pub fn new() -> Self {
Self {
num_states: 0,
start_state: 0,
Expand Down Expand Up @@ -213,8 +215,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
Expand Down Expand Up @@ -264,6 +266,7 @@ mod test {
Box::new(RE::ReOperator::Char('b')),
);
let nfa = NFA::from(&regex);
println!("{:?}", nfa);
let out = serde_json::to_string(&nfa);
panic!("{:?}\n", out.unwrap());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

questo test utile per debuggare, però dovresti fixarlo.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

}
}
Loading