Compare commits

...
This repository has been archived on 2024-04-09. You can view files and clone it, but cannot push or open issues or pull requests.

12 commits

Author SHA1 Message Date
primardj
787063f4b7 add quote gestion 2024-01-18 14:46:44 +00:00
primardj
fc7129d16d terminer la cas ou il y à un caractère vide de reçu 2024-01-16 21:11:34 +00:00
primardj
40cf5ee7ad create new function to contain the final case, add a new type of structure comments 2024-01-16 14:11:40 +00:00
primardj
02278d482c correction objet Structure & ajout fonction parser_word & ajout cas ou il ne reste plus rien à parser. 2024-01-15 17:55:58 +00:00
primardj
5790875ce5 retirer tout un tas de commentaires innutiles. 2024-01-14 19:15:20 +00:00
primardj
430491e125 ajout du constructeur Structure vide terminaision de la fonction parse2 et création de la fonction parse_initial 2024-01-14 19:12:44 +00:00
primardj
79f52c87cd add some comments to explain objects/mod.rs 2024-01-14 18:01:33 +00:00
primardj
d1d31a7d15 create folder objects to contains Structure and Entree 2024-01-14 17:54:27 +00:00
primardj
a09c5024e7 debut reflexion nouveau parseur + ajout Structure::add_to_contents Entree::add_structure et mise public des methodes Structure::get_name et Structure::get_contents 2024-01-13 20:52:07 +00:00
primardj
2f6d4ea4e1 correction Entree.add_structure, j'avais oublié d'incrémenter size lorsqu'une Structure est ajoutée. 2024-01-11 19:36:18 +00:00
primardj
f3491fb333 mise en place correctement des commantaires, et permière version des objets Structure et Entree. Plus qu'as modifier parser.rs et buffer.rs pour les tester 2024-01-11 19:33:27 +00:00
primardj
da52af342b creation de la structure Entree et de la structure Structure. Une entrée contient une liste de structure. 2024-01-11 00:09:40 +00:00
5 changed files with 320 additions and 0 deletions

View file

@ -3,6 +3,7 @@ mod parser;
mod job;
mod variables;
mod error;
mod objects;
use std::process::exit;
use variables::Variables;

28
src/objects/entree.rs Normal file
View file

@ -0,0 +1,28 @@
use crate::objects::structure::Structure;
// Définition de l'objet Entree, utilise un object Structure.
pub struct Entree {
/*
* Correspond à une entrée. C'est ce que renvois le parser.
*/
size: i32,
inputs: Vec<Structure>,
}
impl Entree {
pub fn new() -> Self {
Self {
size: 0,
inputs: Vec::new(),
}
}
pub fn add_structure(&mut self, structure: Structure) -> i8 {
self.inputs.push(structure);
self.size +=1;
0
}
}

5
src/objects/mod.rs Normal file
View file

@ -0,0 +1,5 @@
// definition des modules structures et entree pour qu'ils soient accessible aiyeurs dans le code.
pub mod structure;
pub mod entree;

129
src/objects/structure.rs Normal file
View file

@ -0,0 +1,129 @@
// Definition des structures utilisés par le parseur.
// s'utilise par l'appel de la fonction static parse, qui prends en param une ligne de commande
// (Vect<String>) et qui renvois une Entree.
#[derive(Clone)]
pub struct Structure {
/*
* Il y à 5 types de structs differentes.
* - commande
* - control
* - def variable
* - def function
* - pipes
* - commentaires
*/
name: String,
contents: Vec<String>,
}
impl Structure {
/*
* name: "commande"
* contents: ["nom commande", "parametter", "arg1", ...]
*
* parametter define if the command is in background or not. For now, parametter can only be
* either "" or "&"
*/
pub fn new_commande(cont: Vec<String>) -> Self {
Self {
name: String::from("commande"),
contents: cont,
}
}
/*
* name: "control"
* contents: ["if|elif|else|while|for", "condition", "liste String avec (faudra la reparser
* quand on tomberas dessus pour obtenir son objet de classe Entree) "]
*/
fn new_control(cont: Vec<String>) -> Self {
Self {
name: String::from("control"),
contents: cont,
}
}
/*
* name: "variable"
* contents: ["type [string|list]","parametter", "name", "value"]
*
* parametter says if the variable is to export or not. right now it's either "" or "export"
*/
fn new_variable(cont: Vec<String>) -> Self {
Self {
name: String::from("variable"),
contents: cont,
}
}
/*
* name: "function"
* contents: ["name", "nb parametter", "param1", ..., "liste String interieur fonction(faudra
* la repasser quand on tomberas dessus pour obtenir son objet de classe Entree)"]
*/
fn new_function(cont: Vec<String>) -> Self {
Self {
name: String::from("variable"),
contents: cont,
}
}
/*
* name: "pipe"
* contents: ["String Commande1 (faudra la repasser dans le parser)", "String Commande2(tout
* le reste du pipe faudra le repasser dans le parser)"]
*/
fn new_pipe(cont: Vec<String>) -> Self {
Self {
name: String::from("pipe"),
contents: cont,
}
}
/*
* name: "commentaire"
* contents: [une quote]
*
* est utilisé pour dire que l'utilisateur à oublié de refermer sa quote finale.
*
*/
pub fn new_commentaire(cont: String) -> Self {
Self {
name: String::from("commentaire"),
contents: vec![cont],
}
}
pub fn empty() -> Self {
Self {
name: String::new(),
contents: Vec::new(),
}
}
pub fn is_empty(&self) -> bool {
if self.name == "" {
true
} else {
false
}
}
pub fn get_name(&self) -> &String {
&self.name
}
pub fn get_contents(&self) -> &Vec<String> {
&self.contents
}
pub fn add_to_contents(&mut self, word: String) -> Self {
// si le mot n'est pas vide l'ajoutter aux contents.
if word != "" {
let _ = &self.contents.push(word.to_string());
}
self.clone()
}
}

View file

@ -1,3 +1,12 @@
// This is the parser. It can be called by two commands:
// parse(command_line: &String) -> Vec<String>
// parse2(command_line: &String) -> Entree
use crate::objects::entree::Entree;
use crate::objects::structure::Structure;
fn parse_after_whitespace(char_splitted_command_line: &mut Vec<char>, argv: &mut Vec<String>) -> Vec<String> {
let current_char_option = char_splitted_command_line.pop();
@ -33,6 +42,8 @@ fn parse_initial_state(char_splitted_command_line: &mut Vec<char>, current_arg:
}
fn split_string_in_chars(string_to_split: &String) -> Vec<char> {
// découpe une chaine de caractère &String en Vec<char et inverse le pour que
// string_to_split.pop ressorte le premier caractère.
string_to_split.chars().rev().collect()
}
@ -45,3 +56,149 @@ pub fn parse(command_line: &String) -> Vec<String> {
argv
}
// Up to this line is the old version parser.
fn parser_word(word: String) -> Structure {
// Génère à partir d'un mot une structure. Example, si le mot c jaaj=truc, alors cela créerras
// une structure 'variable' si le mot c if|while|for|etc alors cela fait une structure 'control'
// si cela est un mot finissant par () alors cela crée une structure 'fonction' sinon cela crée
// une structure 'commande'
// TODo
// Pour cette deuxieme version du parser, je ne vais pas faire les autres cas.
if word == "" {
// Dans le cas ou la fonction est appellé alors qu'il n'y as pas de mots
Structure::empty()
} else {
// Dans le cas ou aucunes autres structures ne peuvent être crées, créer une structure
// commande avec le mot dedans.
Structure::new_commande(vec![word])
}
}
fn generer_comments_a_partir_stack_quote(mut entree: Entree, mut stack_last_quote: Vec<char>) -> Entree {
// Tant qu'il reste des quotes dans la stack, générer une Structure commentaire
let mut last_quote = stack_last_quote.pop();
if last_quote.is_none() {
// Si il n'y as plus de quote, renvoyer entree
entree
} else {
// Sinon, rajoutter un commentaire à l'entree donnant la quote en question.
entree.add_structure(Structure::new_commentaire(last_quote.expect("last_quote_is_none").to_string()));
generer_comments_a_partir_stack_quote(entree, stack_last_quote)
}
}
fn parse_cas_fin_de_chaine(mut entree: Entree, stack_last_quote: Vec<char>, last_word: String, mut struct_in_construct: Structure) -> Entree {
// Cas final, dans le cas ou le parser recoit un caractère vide.
if struct_in_construct.is_empty() {
// Puisque la structure est vide, essayer de mettre le last_word dans une structure.
struct_in_construct = parser_word(last_word);
if !struct_in_construct.is_empty() {
// si une nouvelle structure est apparue, l'ajoutter à l'entrée.
entree.add_structure(struct_in_construct);
}
} else {
// Dans le cas ou la structure n'est pas vide, ajoutter le mot, et ajoutter la structure.
entree.add_structure(struct_in_construct.add_to_contents(last_word));
}
// Finalement, regarder la stack des ' et ". Pour chaques commentaires ressortis, rajoutter une
// structure commentaire le contenant.
generer_comments_a_partir_stack_quote(entree, stack_last_quote)
}
fn parse_recursif(mut entree: Entree, mut restant_a_parser: Vec<char>, mut stack_last_quote: Vec<char>, mut last_word: String, mut struct_in_construct: Structure) -> Entree {
// Est le parseur initial, commence sa recursivitée avec une entree vide, une ligne de commande
// en char, une pile vide, un mot vide, et une structure vide.
//
// Lis les caractères un par un, et détermine l'action à prendre avec chaques caractères.
// Etape 0; Lis le premier caractère de ce qu'il reste à parser.
let current_char_option = restant_a_parser.pop();
// Etape 1, test cas ou la chaine est vide 'Cas final'
if current_char_option.is_none() {
parse_cas_fin_de_chaine(entree, stack_last_quote, last_word, struct_in_construct)
} else {
let current_char = current_char_option.expect("current_char_is_None");
// Etape 2, regarde si il y as des quotes dans la stack des quotes si oui regarder quel est
// cette quote, et executer en fonction de cela la bonne fonction.
if stack_last_quote[stack_last_quote.len()-1] == '\'' {
// cas ou le quote est ' peu importe le caractère lus autre que ' le mettre dans
// last_word et rappeler parse_recursif.
if current_char == '\'' {
let _ = stack_last_quote.pop();
parse_recursif(entree, restant_a_parser, stack_last_quote, last_word, struct_in_construct)
} else {
last_word.push(current_char);
parse_recursif(entree, restant_a_parser, stack_last_quote, last_word, struct_in_construct)
}
} else if stack_last_quote[stack_last_quote.len()-1] == '"' {
// cas ou quote est " parser caractère sauf si "
// ce cas existe pour au moment ou on rajoutteras la compatibilitée des variables.
if current_char == '"' {
let _ = stack_last_quote.pop();
parse_recursif(entree, restant_a_parser, stack_last_quote, last_word, struct_in_construct)
} else {
last_word.push(current_char);
parse_recursif(entree, restant_a_parser, stack_last_quote, last_word, struct_in_construct)
}
} else {
// maintenant que la stack des quote est vide, regardons si le dernier caractère entré
// est une quote.
if current_char == '"' || current_char == '\'' {
// dans ce cas la, l'ajoutter à la stack
stack_last_quote.push(current_char);
parse_recursif(entree, restant_a_parser, stack_last_quote, last_word, struct_in_construct)
} else if current_char == ';' {
// regardons si c'est le ; caractère de fin de ligne.
// TODO
entree
} else {
// TODO
entree
}
}
//
// Si oui, vérif ';'
// Cas last_word et Structure vide, ignorer le caractère et rappeler le parser_recursif
// Cas contraire, completer structure et l'ajoutter à entrer et rappeler le parser_recursif
//
// si '#' et last_word vide, renvoyer entree
// si ' ' ajoutter last_word à structure, ou, cas ou structure vide, parser_word et
// rappeler le parser_recursif
//
// pour tout les autres cas, ajouter char à last_word.
// TODO
//entree // Ici faudra rappeler le parse_recursif pour passer au caractère suivant.
}
}
pub fn parse2(command_line: &String) -> Entree {
// prends en paramettre un ligne de commande, et retourne une Entree.
let mut entree: Entree = Entree::new();
// Etape 0, découper la commande_line: &String en command_line: Vec<char>
let mut char_splitted_command_line: Vec<char> = split_string_in_chars(&command_line);
// Etape 1, préparer les variables pour lancer le parser recursif
let mut stack_char_empty: Vec<char> = Vec::new();
let mut empty_word: String = String::new();
// Etape 2, lancer le parser recursif. Il retournera une Entree bien parsé comme il faut.
parse_recursif( entree, char_splitted_command_line, stack_char_empty, empty_word, Structure::empty())
}