Compare commits
12 commits
Author | SHA1 | Date | |
---|---|---|---|
|
787063f4b7 | ||
|
fc7129d16d | ||
|
40cf5ee7ad | ||
|
02278d482c | ||
|
5790875ce5 | ||
|
430491e125 | ||
|
79f52c87cd | ||
|
d1d31a7d15 | ||
|
a09c5024e7 | ||
|
2f6d4ea4e1 | ||
|
f3491fb333 | ||
|
da52af342b |
5 changed files with 320 additions and 0 deletions
|
@ -3,6 +3,7 @@ mod parser;
|
||||||
mod job;
|
mod job;
|
||||||
mod variables;
|
mod variables;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod objects;
|
||||||
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use variables::Variables;
|
use variables::Variables;
|
||||||
|
|
28
src/objects/entree.rs
Normal file
28
src/objects/entree.rs
Normal 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
5
src/objects/mod.rs
Normal 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
129
src/objects/structure.rs
Normal 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
157
src/parser.rs
157
src/parser.rs
|
@ -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> {
|
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();
|
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> {
|
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()
|
string_to_split.chars().rev().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,3 +56,149 @@ pub fn parse(command_line: &String) -> Vec<String> {
|
||||||
|
|
||||||
argv
|
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())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Reference in a new issue