From 7f6e51dfea4027de52f3ae706831c13310e8d1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laure=CE=B7t?= Date: Wed, 21 Jun 2023 19:58:18 +0200 Subject: [PATCH] init --- BE/ascendant/Lexer.mll | 55 +++++ BE/ascendant/MainSystem.ml | 52 +++++ BE/ascendant/Parser.mly | 88 +++++++ BE/ascendant/dune | 7 + BE/ascendant/dune-project | 2 + BE/descendant/MainSystem.ml | 25 ++ BE/descendant/Parser.ml | 303 +++++++++++++++++++++++++ BE/descendant/Scanner.mll | 55 +++++ BE/descendant/Tokens.ml | 88 +++++++ BE/descendant/dune | 4 + BE/descendant/dune-project | 1 + BE/tests/sujet.sdl | 11 + BE_2020_2021/ascendant/Lexer.mll | 43 ++++ BE_2020_2021/ascendant/MainMachine.ml | 41 ++++ BE_2020_2021/ascendant/Parser.mly | 71 ++++++ BE_2020_2021/ascendant/dune | 7 + BE_2020_2021/ascendant/dune-project | 2 + BE_2020_2021/descendant/MainMachine.ml | 25 ++ BE_2020_2021/descendant/Parser.ml | 239 +++++++++++++++++++ BE_2020_2021/descendant/Scanner.mll | 43 ++++ BE_2020_2021/descendant/Tokens.ml | 68 ++++++ BE_2020_2021/descendant/dune | 4 + BE_2020_2021/descendant/dune-project | 1 + BE_2020_2021/tests/sujet.sml | 10 + BE_2020_2021/tests/test-KO-00.sml | 1 + BE_2020_2021/tests/test-OK-00.sml | 2 + BE_2021_2022/ascendant/Lexer.mll | 55 +++++ BE_2021_2022/ascendant/MainSystem.ml | 52 +++++ BE_2021_2022/ascendant/Parser.mly | 88 +++++++ BE_2021_2022/ascendant/dune | 7 + BE_2021_2022/ascendant/dune-project | 2 + BE_2021_2022/descendant/MainSystem.ml | 25 ++ BE_2021_2022/descendant/Parser.ml | 303 +++++++++++++++++++++++++ BE_2021_2022/descendant/Scanner.mll | 55 +++++ BE_2021_2022/descendant/Tokens.ml | 88 +++++++ BE_2021_2022/descendant/dune | 4 + BE_2021_2022/descendant/dune-project | 1 + BE_2021_2022/tests/sujet.sdl | 11 + TP1/dune | 5 + TP1/dune-project | 3 + TP1/lexerJava.mll | 95 ++++++++ TP1/mainJava.ml | 12 + TP1/tests/exemple-complique.java | 49 ++++ TP1/tests/exemple-simple.java | 32 +++ TP1/tests/exemple-tres-simple.java | 3 + TP1/tests/exemple.java | 2 + TP1/tests/test.java | 11 + TP1/tokenJava.ml | 121 ++++++++++ TP1/tokenJava.mli | 65 ++++++ TP2/dune | 7 + TP2/dune-project | 5 + TP2/lexerJava.mll | 82 +++++++ TP2/mainJava.ml | 71 ++++++ TP2/parserJava.mly | 165 ++++++++++++++ TP2/tests/exemple-complique.java | 49 ++++ TP2/tests/exemple-simple.java | 32 +++ TP2/tests/exemple-tres-simple.java | 3 + TP2/tests/exemple.java | 2 + TP2/tests/test.java | 3 + TP2/tests/test00.java | 30 +++ TP3/A_FAIRE.txt | 145 ++++++++++++ TP3/Lex.ml | 88 +++++++ TP3/Main.ml | 22 ++ TP3/MainMonad.ml | 22 ++ TP3/Scanner.mll | 118 ++++++++++ TP3/Syntax.ml | 209 +++++++++++++++++ TP3/SyntaxMonad.ml | 288 +++++++++++++++++++++++ TP3/dune | 4 + TP3/dune-project | 1 + TP3/tests/test.ml | 27 +++ 70 files changed, 3710 insertions(+) create mode 100755 BE/ascendant/Lexer.mll create mode 100755 BE/ascendant/MainSystem.ml create mode 100755 BE/ascendant/Parser.mly create mode 100755 BE/ascendant/dune create mode 100755 BE/ascendant/dune-project create mode 100755 BE/descendant/MainSystem.ml create mode 100755 BE/descendant/Parser.ml create mode 100755 BE/descendant/Scanner.mll create mode 100755 BE/descendant/Tokens.ml create mode 100755 BE/descendant/dune create mode 100755 BE/descendant/dune-project create mode 100755 BE/tests/sujet.sdl create mode 100755 BE_2020_2021/ascendant/Lexer.mll create mode 100755 BE_2020_2021/ascendant/MainMachine.ml create mode 100755 BE_2020_2021/ascendant/Parser.mly create mode 100755 BE_2020_2021/ascendant/dune create mode 100755 BE_2020_2021/ascendant/dune-project create mode 100755 BE_2020_2021/descendant/MainMachine.ml create mode 100755 BE_2020_2021/descendant/Parser.ml create mode 100755 BE_2020_2021/descendant/Scanner.mll create mode 100755 BE_2020_2021/descendant/Tokens.ml create mode 100755 BE_2020_2021/descendant/dune create mode 100755 BE_2020_2021/descendant/dune-project create mode 100755 BE_2020_2021/tests/sujet.sml create mode 100755 BE_2020_2021/tests/test-KO-00.sml create mode 100755 BE_2020_2021/tests/test-OK-00.sml create mode 100644 BE_2021_2022/ascendant/Lexer.mll create mode 100644 BE_2021_2022/ascendant/MainSystem.ml create mode 100644 BE_2021_2022/ascendant/Parser.mly create mode 100644 BE_2021_2022/ascendant/dune create mode 100644 BE_2021_2022/ascendant/dune-project create mode 100644 BE_2021_2022/descendant/MainSystem.ml create mode 100644 BE_2021_2022/descendant/Parser.ml create mode 100644 BE_2021_2022/descendant/Scanner.mll create mode 100644 BE_2021_2022/descendant/Tokens.ml create mode 100644 BE_2021_2022/descendant/dune create mode 100644 BE_2021_2022/descendant/dune-project create mode 100644 BE_2021_2022/tests/sujet.sdl create mode 100755 TP1/dune create mode 100755 TP1/dune-project create mode 100755 TP1/lexerJava.mll create mode 100755 TP1/mainJava.ml create mode 100755 TP1/tests/exemple-complique.java create mode 100755 TP1/tests/exemple-simple.java create mode 100755 TP1/tests/exemple-tres-simple.java create mode 100755 TP1/tests/exemple.java create mode 100755 TP1/tests/test.java create mode 100755 TP1/tokenJava.ml create mode 100755 TP1/tokenJava.mli create mode 100755 TP2/dune create mode 100755 TP2/dune-project create mode 100755 TP2/lexerJava.mll create mode 100755 TP2/mainJava.ml create mode 100755 TP2/parserJava.mly create mode 100755 TP2/tests/exemple-complique.java create mode 100755 TP2/tests/exemple-simple.java create mode 100755 TP2/tests/exemple-tres-simple.java create mode 100755 TP2/tests/exemple.java create mode 100755 TP2/tests/test.java create mode 100755 TP2/tests/test00.java create mode 100755 TP3/A_FAIRE.txt create mode 100755 TP3/Lex.ml create mode 100755 TP3/Main.ml create mode 100755 TP3/MainMonad.ml create mode 100755 TP3/Scanner.mll create mode 100755 TP3/Syntax.ml create mode 100755 TP3/SyntaxMonad.ml create mode 100755 TP3/dune create mode 100755 TP3/dune-project create mode 100755 TP3/tests/test.ml diff --git a/BE/ascendant/Lexer.mll b/BE/ascendant/Lexer.mll new file mode 100755 index 0000000..c992211 --- /dev/null +++ b/BE/ascendant/Lexer.mll @@ -0,0 +1,55 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open Parser + exception LexicalError + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let entier = ['1' - '9'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaire = + (* Commentaire fin de ligne *) + "#" [^'\n']* + +rule lexer = parse + | ['\n' '\t' ' ']+ { (lexer lexbuf) } + | commentaire { (lexer lexbuf) } + | "model" { UL_MODEL } + | "system" { UL_SYSTEM } + | "block" { UL_BLOCK } + | "flow" { UL_FLOW } + | "from" { UL_FROM } + | "to" { UL_TO } + | "in" { UL_IN } + | "out" { UL_OUT } + | "int" { UL_INT } + | "float" { UL_FLOAT } + | "boolean" { UL_BOOLEAN } + | "{" { UL_ACCOUV } + | "}" { UL_ACCFER } + | "(" { UL_PAROUV } + | ")" { UL_PARFER } + | "[" { UL_CROOUV } + | "]" { UL_CROFER } + | ";" { UL_PTV } + | "," { UL_VIRG } + | ":" { UL_PT2 } + | "." { UL_PT } + | eof { UL_FIN } + | majuscule alphabet* as texte { (UL_IDENT texte) } + | minuscule alphabet* as texte { (UL_PORT texte) } + | entier chiffre* as texte { (UL_ENTIER (int_of_string texte)) } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); raise LexicalError } + +{ + +} diff --git a/BE/ascendant/MainSystem.ml b/BE/ascendant/MainSystem.ml new file mode 100755 index 0000000..69c4f9b --- /dev/null +++ b/BE/ascendant/MainSystem.ml @@ -0,0 +1,52 @@ +open Parser + +(* Fonction d'affichage des unités lexicales et des données qu'elles contiennent *) +let printToken t = + (print_endline + (match t with + | UL_MODEL -> "model" + | UL_SYSTEM -> "system" + | UL_BLOCK -> "block" + | UL_FLOW -> "flow" + | UL_FROM -> "from" + | UL_TO -> "to" + | UL_IN -> "in" + | UL_OUT -> "out" + | UL_INT -> "int" + | UL_FLOAT -> "float" + | UL_BOOLEAN -> "boolean" + | UL_ACCOUV -> "{" + | UL_ACCFER -> "}" + | UL_PAROUV -> "(" + | UL_PARFER -> ")" + | UL_CROOUV -> "[" + | UL_CROFER -> "]" + | UL_PTV -> ";" + | UL_VIRG -> "," + | UL_PT2 -> ":" + | UL_PT -> "." + | UL_IDENT texte -> texte + | UL_PORT texte -> texte + | UL_ENTIER texte -> (string_of_int texte) + | UL_FIN -> "EOF" +));; + +(* Analyse lexicale du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + let token = ref (Lexer.lexer lexbuf) in + while ((!token) != UL_FIN) do + (printToken (!token)); + (token := (Lexer.lexer lexbuf)) + done +else + (print_endline "MainJSON fichier");; + +(* Analyse lexicale, syntaxique et sémantique du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + (Parser.modele Lexer.lexer lexbuf) +else + (print_endline "MainJSON fichier");; diff --git a/BE/ascendant/Parser.mly b/BE/ascendant/Parser.mly new file mode 100755 index 0000000..dec6e96 --- /dev/null +++ b/BE/ascendant/Parser.mly @@ -0,0 +1,88 @@ +%{ + +(* Partie recopiee dans le fichier CaML genere. *) +(* Ouverture de modules exploites dans les actions *) +(* Declarations de types, de constantes, de fonctions, d'exceptions exploites dans les actions *) + +%} + +/* Declaration des unites lexicales et de leur type si une valeur particuliere leur est associee */ + +%token UL_MODEL +%token UL_ACCOUV UL_ACCFER +%token UL_SYSTEM +%token UL_BLOCK +%token UL_FLOW UL_FROM UL_TO +%token UL_IN UL_OUT +%token UL_INT UL_FLOAT UL_BOOLEAN +%token UL_PAROUV UL_PARFER +%token UL_CROOUV UL_CROFER +%token UL_PTV UL_VIRG UL_PT2 UL_PT + +/* Defini le type des donnees associees a l'unite lexicale */ + +%token UL_IDENT +%token UL_PORT +%token UL_ENTIER + +/* Unite lexicale particuliere qui represente la fin du fichier */ + +%token UL_FIN + +/* Type renvoye pour le nom terminal document */ +%type modele + +/* Le non terminal document est l'axiome */ +%start modele + +%% /* Regles de productions */ + +modele : UL_MODEL UL_IDENT UL_ACCOUV loop_element UL_ACCFER UL_FIN { (print_endline "modele : UL_MODEL IDENT { loop_element } UL_FIN ") } + +element : bloc { (print_endline "element : bloc") } + | systeme { (print_endline "element : systeme") } + | flot { (print_endline "element : flot") } + +loop_element : /* Lambda */ { (print_endline "loop_element : /* Lambda */") } + | element loop_element { (print_endline "loop_element : element loop_element") } + +bloc : UL_BLOCK UL_IDENT parametres UL_PTV { (print_endline "bloc : UL_BLOCK UL_IDENT parametres UL_PTV") } + +systeme : UL_SYSTEM UL_IDENT parametres UL_ACCOUV loop_element UL_ACCFER { (print_endline "systeme : UL_SYSTEM UL_IDENT parametres UL_ACCOUV loop_element UL_ACCFER") } + +parametres : UL_PAROUV port loop_port UL_PARFER { (print_endline "parametres : UL_PAROUV port loop_port UL_PARFER") } + +loop_port : /* Lambda */ { (print_endline "loop_port : /* Lambda */") } + | UL_VIRG port loop_port { (print_endline "loop_port : UL_VIRG port loop_port") } + +port : UL_PORT UL_PT2 in_or_out type_ { (print_endline "port : UL_PORT UL_PT2 in_or_out type_") } + +in_or_out : UL_IN { (print_endline "in_or_out : UL_IN") } + | UL_OUT { (print_endline "in_or_out : UL_OUT") } + +type_ : select_type option_entiers { (print_endline "type_ : select_type option_entiers") } + +select_type : UL_INT { (print_endline "select_type : UL_INT") } + | UL_FLOAT { (print_endline "select_type : UL_FLOAT") } + | UL_BOOLEAN { (print_endline "select_type : UL_BOOLEAN") } + +option_entiers : /* Lambda */ { (print_endline "option_entiers : /* Lambda */") } + | UL_CROOUV UL_ENTIER loop_entier UL_CROFER { (print_endline "option_entiers : UL_CROOUV UL_ENTIER loop_entier UL_CROFER") } + +loop_entier : /* Lambda */ { (print_endline "loop_entier : /* Lambda */") } + | UL_VIRG UL_ENTIER loop_entier { (print_endline "loop_entier : UL_VIRG UL_ENTIER loop_entier") } + +flot : UL_FLOW UL_PORT UL_FROM option_ident UL_PORT UL_TO option_loop_ident_port UL_PTV { (print_endline "flot : UL_FLOW UL_PORT UL_FROM option_ident UL_PORT UL_TO option_loop_ident_port UL_PTV") } + +option_ident : /* Lambda */ { (print_endline "option_ident : /* Lambda */") } + | UL_IDENT UL_PT { (print_endline "option_ident : UL_IDENT UL_PT") } + +ident_port : option_ident UL_PORT { (print_endline "ident_port : option_ident UL_PORT") } + +loop_ident_port : /* Lambda */ { (print_endline "loop_ident_port : /* Lambda */") } + | UL_VIRG ident_port loop_ident_port { (print_endline "loop_ident_port : UL_IDENT UL_PT") } + +option_loop_ident_port : /* Lambda */ { (print_endline "option_loop_ident_port : /* Lambda */") } + | ident_port loop_ident_port { (print_endline "option_loop_ident_port : ident_port loop_ident_port") } + +%% diff --git a/BE/ascendant/dune b/BE/ascendant/dune new file mode 100755 index 0000000..6158748 --- /dev/null +++ b/BE/ascendant/dune @@ -0,0 +1,7 @@ +(ocamllex Lexer) + +(menhir + (modules Parser)) + +(executable + (name MainSystem)) diff --git a/BE/ascendant/dune-project b/BE/ascendant/dune-project new file mode 100755 index 0000000..192d77f --- /dev/null +++ b/BE/ascendant/dune-project @@ -0,0 +1,2 @@ +(lang dune 2.9) +(using menhir 2.1) diff --git a/BE/descendant/MainSystem.ml b/BE/descendant/MainSystem.ml new file mode 100755 index 0000000..8a4ee02 --- /dev/null +++ b/BE/descendant/MainSystem.ml @@ -0,0 +1,25 @@ +open Tokens +open Scanner +open Parser + +(* main : unit -> unit *) +(* Analyse le contenu d'un fichier passé en paramètre ou l'entrée standard si aucun fichier n'est donné *) +(* Affiche OK si l'analyse syntaxique c'est bien passée et KO sinon *) +let main () = + let cin = + if Array.length Sys.argv > 1 then + open_in Sys.argv.(1) + else + stdin + in + let lexbuf = Lexing.from_channel cin in + let tokens = (scanner lexbuf) in + (print_endline ("Résultat de l'analyse lexicale :" ^ (string_of_stream tokens))); + (print_endline "Analyse syntaxique par descente récursive, règles appliquées :"); + (match (parseR tokens) + with + | Success [UL_FIN] -> print_endline "Succés" + | _ -> print_endline "Echec") +;; + +main();; diff --git a/BE/descendant/Parser.ml b/BE/descendant/Parser.ml new file mode 100755 index 0000000..8cfbbc1 --- /dev/null +++ b/BE/descendant/Parser.ml @@ -0,0 +1,303 @@ +open Tokens + +(* Type du résultat d'une analyse syntaxique *) +type parseResult = + | Success of inputStream + | Failure +;; + +(* accept : token -> inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien le token attendu *) +(* et avance dans l'analyse si c'est le cas *) +let accept expected stream = + match (peekAtFirstToken stream) with + | token when (token = expected) -> + (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptIdent : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un identifiant *) +(* et avance dans l'analyse si c'est le cas *) +let acceptIdent stream = + match (peekAtFirstToken stream) with + | (UL_IDENT _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptPort : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un port *) +(* et avance dans l'analyse si c'est le cas *) +let acceptPort stream = + match (peekAtFirstToken stream) with + | (UL_PORT _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptEntier : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un entier *) +(* et avance dans l'analyse si c'est le cas *) +let acceptEntier stream = + match (peekAtFirstToken stream) with + | (UL_ENTIER _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* Définition de la monade qui est composée de : *) +(* - le type de donnée monadique : parseResult *) +(* - la fonction : inject qui construit ce type à partir d'une liste de terminaux *) +(* - la fonction : bind (opérateur >>=) qui combine les fonctions d'analyse. *) + +(* inject inputStream -> parseResult *) +(* Construit le type de la monade à partir d'une liste de terminaux *) +let inject s = Success s;; + +(* bind : 'a m -> ('a -> 'b m) -> 'b m *) +(* bind (opérateur >>=) qui combine les fonctions d'analyse. *) +(* ici on utilise une version spécialisée de bind : + 'b -> inputStream + 'a -> inputStream + m -> parseResult +*) +(* >>= : parseResult -> (inputStream -> parseResult) -> parseResult *) +let (>>=) result f = + match result with + | Success next -> f next + | Failure -> Failure +;; + + +(* parseR : inputStream -> parseResult *) +(* Analyse du non terminal Programme *) +let rec parseR stream = + (print_string "R"); + (match (peekAtFirstToken stream) with + (* 1. R -> model Ident { SE } *) + | UL_MODEL -> + inject stream >>= + accept UL_MODEL >>= + acceptIdent >>= + accept UL_ACCOUV >>= + parseSE >>= + accept UL_ACCFER + (* Failure *) + | _ -> Failure) + +(* parseSE : inputStream -> parseResult *) +and parseSE stream = + (print_endline "SE"); + (match (peekAtFirstToken stream) with + (* 2. SE -> Λ *) + | UL_ACCFER -> + inject stream + (* 3. SE -> E SE *) + | ( UL_BLOCK | UL_SYSTEM | UL_FLOW ) -> + inject stream >>= + parseE >>= + parseSE + (* Failure *) + | _ -> Failure) + +(* parseE : inputStream -> parseResult *) +and parseE stream = + (print_endline "E"); + (match (peekAtFirstToken stream) with + (* 4. E -> block Ident P ; *) + | UL_BLOCK -> + inject stream >>= + accept UL_BLOCK >>= + acceptIdent >>= + parseP >>= + accept UL_PTV + (* 5. E -> system Ident P { SE } *) + | UL_SYSTEM -> + inject stream >>= + accept UL_SYSTEM >>= + acceptIdent >>= + parseP >>= + accept UL_ACCOUV >>= + parseSE >>= + accept UL_ACCFER + (* 6. E -> flow ident from NQ to LN ; *) + | UL_FLOW -> + inject stream >>= + accept UL_FLOW >>= + acceptPort >>= + accept UL_FROM >>= + parseNQ >>= + accept UL_TO >>= + parseLN >>= + accept UL_PTV + (* Failure *) + | _ -> Failure) + +(* parseNQ : inputStream -> parseResult *) +and parseNQ stream = + (print_endline "NQ"); + (match (peekAtFirstToken stream) with + (* 7. NQ -> ident *) + | (UL_PORT _) -> + inject stream >>= + acceptPort + (* 8. NQ -> Ident . ident *) + | (UL_IDENT _) -> + inject stream >>= + acceptIdent >>= + accept UL_PT >>= + acceptPort + (* Failure *) + | _ -> Failure) + +(* parseLN : inputStream -> parseResult *) +and parseLN stream = + (print_endline "LN"); + (match (peekAtFirstToken stream) with + (* 9. LN -> Λ *) + | UL_PTV -> + inject stream + (* 10. LN -> NQ SN *) + | ( (UL_IDENT _) | (UL_PORT _) ) -> + inject stream >>= + parseNQ >>= + parseSN + (* Failure *) + | _ -> Failure) + +(* parseSN : inputStream -> parseResult *) +and parseSN stream = + (print_endline "SN"); + (match (peekAtFirstToken stream) with + (* 11. SN -> Λ *) + | UL_PTV -> + inject stream + (* 12. LN -> , NQ SN *) + | UL_VIRG -> + inject stream >>= + accept UL_VIRG >>= + parseNQ >>= + parseSN + (* Failure *) + | _ -> Failure) + +(* parseP : inputStream -> parseResult *) +and parseP stream = + (print_endline "P"); + (match (peekAtFirstToken stream) with + (* 13. P -> ( LP ) *) + | UL_PAROUV -> + inject stream >>= + accept UL_PAROUV >>= + parseLP >>= + accept UL_PARFER + (* Failure *) + | _ -> Failure) + +(* parseLP : inputStream -> parseResult *) +and parseLP stream = + (print_endline "LP"); + (match (peekAtFirstToken stream) with + (* 14. LP -> DP SP *) + | (UL_PORT _) -> + inject stream >>= + parseDP >>= + parseSP + (* Failure *) + | _ -> Failure) + +(* parseSP : inputStream -> parseResult *) +and parseSP stream = + (print_endline "SP"); + (match (peekAtFirstToken stream) with + (* 15. SP -> Λ *) + | UL_PARFER -> + inject stream + (* 16. LN -> , DP SP *) + | UL_VIRG -> + inject stream >>= + accept UL_VIRG >>= + parseDP >>= + parseSP + (* Failure *) + | _ -> Failure) + +(* parseDP : inputStream -> parseResult *) +and parseDP stream = + (print_endline "DP"); + (match (peekAtFirstToken stream) with + (* 17. LP -> ident : M T OT *) + | (UL_PORT _) -> + inject stream >>= + acceptPort >>= + accept UL_PT2 >>= + parseM >>= + parseT >>= + parseOT + (* Failure *) + | _ -> Failure) + +(* parseM : inputStream -> parseResult *) +and parseM stream = + (print_endline "M"); + (match (peekAtFirstToken stream) with + (* 18. M -> in *) + | UL_IN -> + inject stream >>= + accept UL_IN + (* 19. M -> out *) + | UL_OUT -> + inject stream >>= + accept UL_OUT + (* Failure *) + | _ -> Failure) + +(* parseT : inputStream -> parseResult *) +and parseT stream = + (print_endline "T"); + (match (peekAtFirstToken stream) with + (* 20. T -> int *) + | UL_INT -> + inject stream >>= + accept UL_INT + (* 21. M -> float *) + | UL_FLOAT -> + inject stream >>= + accept UL_FLOAT + (* 22. M -> boolean *) + | UL_BOOLEAN -> + inject stream >>= + accept UL_BOOLEAN + (* Failure *) + | _ -> Failure) + +(* parseOT : inputStream -> parseResult *) +and parseOT stream = + (print_endline "OT"); + (match (peekAtFirstToken stream) with + (* 23. OT -> Λ *) + | ( UL_VIRG | UL_PARFER ) -> + inject stream + (* 24. OT -> [ entier SV ] *) + | UL_CROOUV -> + inject stream >>= + accept UL_CROOUV >>= + acceptEntier >>= + parseSV >>= + accept UL_CROFER + (* Failure *) + | _ -> Failure) + +(* parseSV : inputStream -> parseResult *) +and parseSV stream = + (print_endline "SV"); + (match (peekAtFirstToken stream) with + (* 25. OT -> Λ *) + | UL_CROFER -> + inject stream + (* 26. OT -> , entier SV *) + | UL_VIRG -> + inject stream >>= + accept UL_VIRG >>= + acceptEntier >>= + parseSV + (* Failure *) + | _ -> Failure) diff --git a/BE/descendant/Scanner.mll b/BE/descendant/Scanner.mll new file mode 100755 index 0000000..9b0decd --- /dev/null +++ b/BE/descendant/Scanner.mll @@ -0,0 +1,55 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open Tokens + exception Printf + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let entier = ['1' - '9'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaire = + (* Commentaire fin de ligne *) + "#" [^'\n']* + +rule scanner = parse + | ['\n' '\t' ' ']+ { (scanner lexbuf) } + | commentaire { (scanner lexbuf) } + | "model" { UL_MODEL::(scanner lexbuf) } + | "system" { UL_SYSTEM::(scanner lexbuf) } + | "block" { UL_BLOCK::(scanner lexbuf) } + | "flow" { UL_FLOW::(scanner lexbuf) } + | "from" { UL_FROM::(scanner lexbuf) } + | "to" { UL_TO::(scanner lexbuf) } + | "in" { UL_IN::(scanner lexbuf) } + | "out" { UL_OUT::(scanner lexbuf) } + | "int" { UL_INT::(scanner lexbuf) } + | "float" { UL_FLOAT::(scanner lexbuf) } + | "boolean" { UL_BOOLEAN::(scanner lexbuf) } + | "{" { UL_ACCOUV::(scanner lexbuf) } + | "}" { UL_ACCFER::(scanner lexbuf) } + | "(" { UL_PAROUV::(scanner lexbuf) } + | ")" { UL_PARFER::(scanner lexbuf) } + | "[" { UL_CROOUV::(scanner lexbuf) } + | "]" { UL_CROFER::(scanner lexbuf) } + | ";" { UL_PTV::(scanner lexbuf) } + | "," { UL_VIRG::(scanner lexbuf) } + | ":" { UL_PT2::(scanner lexbuf) } + | "." { UL_PT::(scanner lexbuf) } + | majuscule alphabet* as texte { (UL_IDENT texte)::(scanner lexbuf) } + | minuscule alphabet* as texte { (UL_PORT texte)::(scanner lexbuf) } + | entier chiffre* as texte { (UL_ENTIER (int_of_string texte))::(scanner lexbuf) } + | eof { [UL_FIN] } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); (UL_ERREUR::(scanner lexbuf)) } + +{ + +} diff --git a/BE/descendant/Tokens.ml b/BE/descendant/Tokens.ml new file mode 100755 index 0000000..0af51dd --- /dev/null +++ b/BE/descendant/Tokens.ml @@ -0,0 +1,88 @@ +open List + +type token = + | UL_MODEL + | UL_SYSTEM + | UL_BLOCK + | UL_FLOW + | UL_FROM + | UL_TO + | UL_IN + | UL_OUT + | UL_INT + | UL_FLOAT + | UL_BOOLEAN + | UL_ACCOUV + | UL_ACCFER + | UL_PAROUV + | UL_PARFER + | UL_CROOUV + | UL_CROFER + | UL_PTV + | UL_VIRG + | UL_PT2 + | UL_PT + | UL_IDENT of string + | UL_PORT of string + | UL_ENTIER of int + | UL_FIN + | UL_ERREUR;; + +type inputStream = token list;; + +(* string_of_token : token -> string *) +(* Converti un token en une chaîne de caractère*) +let string_of_token token = + match token with + | UL_MODEL -> "model" + | UL_SYSTEM -> "system" + | UL_BLOCK -> "block" + | UL_FLOW -> "flow" + | UL_FROM -> "from" + | UL_TO -> "to" + | UL_IN -> "in" + | UL_OUT -> "out" + | UL_INT -> "int" + | UL_FLOAT -> "float" + | UL_BOOLEAN -> "boolean" + | UL_ACCOUV -> "{" + | UL_ACCFER -> "}" + | UL_PAROUV -> "(" + | UL_PARFER -> ")" + | UL_CROOUV -> "[" + | UL_CROFER -> "]" + | UL_PTV -> ";" + | UL_VIRG -> "," + | UL_PT2 -> ":" + | UL_PT -> "." + | UL_IDENT texte -> texte + | UL_PORT texte -> texte + | UL_ENTIER texte -> (string_of_int texte) + | UL_FIN -> "EOF" + | UL_ERREUR -> "Erreur Lexicale";; + +(* string_of_stream : inputStream -> string *) +(* Converti un inputStream (liste de token) en une chaîne de caractère *) +let string_of_stream stream = + List.fold_right (fun t tq -> (string_of_token t) ^ " " ^ tq ) stream "";; + + +(* peekAtFirstToken : inputStream -> token *) +(* Renvoie le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let peekAtFirstToken stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible d'acceder au premier element d'un inputStream vide" + |t::_ -> t;; + +(* advanceInStream : inputStream -> inputStream *) +(* Consomme le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let advanceInStream stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible de consommer le premier element d'un inputStream vide" + | _::q -> q;; diff --git a/BE/descendant/dune b/BE/descendant/dune new file mode 100755 index 0000000..5fc66e2 --- /dev/null +++ b/BE/descendant/dune @@ -0,0 +1,4 @@ +(ocamllex Scanner) + +(executables + (names MainSystem)) diff --git a/BE/descendant/dune-project b/BE/descendant/dune-project new file mode 100755 index 0000000..c994249 --- /dev/null +++ b/BE/descendant/dune-project @@ -0,0 +1 @@ +(lang dune 2.9) diff --git a/BE/tests/sujet.sdl b/BE/tests/sujet.sdl new file mode 100755 index 0000000..05f7d04 --- /dev/null +++ b/BE/tests/sujet.sdl @@ -0,0 +1,11 @@ +model S { + flow f from Ba.ra to HS.pa, HS.pb; + block Ba(pa : in float, pb : in float, ra : out float [ 2 ] ); + system HS(pa : in float [ 2 ], ra : out float, pb : in float [ 2 ] , rb : out float [ 2 ] ) { + block Bb(ra : out float, pa : in float); + flow fa from pa to Bb.pa; + flow fb from pb to rb; + } + flow fb from HS.ra to Ba.pa, Ba.pb; + flow fc from HS.rb to; +} diff --git a/BE_2020_2021/ascendant/Lexer.mll b/BE_2020_2021/ascendant/Lexer.mll new file mode 100755 index 0000000..37af00f --- /dev/null +++ b/BE_2020_2021/ascendant/Lexer.mll @@ -0,0 +1,43 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open Parser + exception LexicalError + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaire = + (* Commentaire fin de ligne *) + "#" [^'\n']* + +rule lexer = parse + | ['\n' '\t' ' ']+ { (lexer lexbuf) } + | commentaire { (lexer lexbuf) } + | "{" { UL_ACCOUV } + | "}" { UL_ACCFER } + | "." { UL_PT } + | "machine" { UL_MACHINE } + | "to" { UL_TO } + | "on" { UL_ON } + | "event" { UL_EVENT } + | "from" { UL_FROM } + | "region" { UL_REGION } + | "ends" { UL_ENDS } + | "starts" { UL_STARTS } + | "state" { UL_STATE } + | eof { UL_FIN } + | alphabet+ as texte { (UL_IDENT texte) } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); raise LexicalError } + +{ + +} diff --git a/BE_2020_2021/ascendant/MainMachine.ml b/BE_2020_2021/ascendant/MainMachine.ml new file mode 100755 index 0000000..b912c62 --- /dev/null +++ b/BE_2020_2021/ascendant/MainMachine.ml @@ -0,0 +1,41 @@ +open Parser + +(* Fonction d'affichage des unités lexicales et des données qu'elles contiennent *) +let printToken t = + (print_endline + (match t with + | UL_IDENT (texte) -> texte + | UL_ACCOUV -> "{" + | UL_ACCFER -> "}" + | UL_PT -> "." + | UL_MACHINE -> "machine" + | UL_TO -> "to" + | UL_ON -> "on" + | UL_EVENT -> "event" + | UL_FROM -> "from" + | UL_REGION -> "region" + | UL_ENDS -> "ends" + | UL_STARTS -> "starts" + | UL_STATE -> "state" + | UL_FIN -> "EOF" +));; + +(* Analyse lexicale du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + let token = ref (Lexer.lexer lexbuf) in + while ((!token) != UL_FIN) do + (printToken (!token)); + (token := (Lexer.lexer lexbuf)) + done +else + (print_endline "MainJSON fichier");; + +(* Analyse lexicale, syntaxique et sémantique du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + (Parser.machine Lexer.lexer lexbuf) +else + (print_endline "MainJSON fichier");; diff --git a/BE_2020_2021/ascendant/Parser.mly b/BE_2020_2021/ascendant/Parser.mly new file mode 100755 index 0000000..0ce05ed --- /dev/null +++ b/BE_2020_2021/ascendant/Parser.mly @@ -0,0 +1,71 @@ +%{ + +(* Partie recopiee dans le fichier CaML genere. *) +(* Ouverture de modules exploites dans les actions *) +(* Declarations de types, de constantes, de fonctions, d'exceptions exploites dans les actions *) + +%} + +/* Declaration des unites lexicales et de leur type si une valeur particuliere leur est associee */ + +%token UL_MACHINE +%token UL_ACCOUV UL_ACCFER +%token UL_FROM UL_TO UL_ON +%token UL_STARTS UL_ENDS +%token UL_REGION +%token UL_STATE +%token UL_EVENT +%token UL_PT + +/* Defini le type des donnees associees a l'unite lexicale */ + +%token UL_IDENT + +/* Unite lexicale particuliere qui represente la fin du fichier */ + +%token UL_FIN + +/* Type renvoye pour le nom terminal document */ +%type machine + +/* Le non terminal document est l'axiome */ +%start machine + +%% /* Regles de productions */ + +machine : UL_MACHINE UL_IDENT UL_ACCOUV loop_composant UL_ACCFER UL_FIN { (print_endline "machine : MACHINE IDENT ACCOUV loop_composant ACCFER FIN") } + +composant : UL_EVENT UL_IDENT { (print_endline "composant : EVENT IDENT") } + | transition { (print_endline "composant : transition") } + | region { (print_endline "composant : region") } + +transition : UL_FROM nom_qualifie UL_TO nom_qualifie UL_ON UL_IDENT { (print_endline "transition : FROM nom_qualifie TO nom_qualifie ON IDENT") } + +nom_qualifie : UL_IDENT loop_nom_qualfie { (print_endline "nom_qualifie : IDENT loop_nom_qualifie") } + +etat : UL_STATE UL_IDENT option_starts option_ends option_regions { (print_endline "etat : STATE IDENT option_starts option_ends option_regions") } + +region : UL_REGION UL_IDENT UL_ACCOUV etat loop_etat UL_ACCFER { (print_endline "region : REGION IDENT ACCOUV etat loop_etat ACCFER") } + +loop_composant : /* Lambda, mot vide */ { (print_endline "loop_composant : /* Lambda, mot vide */") } + | composant loop_composant { (print_endline "loop_composant : composant loop_composant") } + +loop_nom_qualfie : /* Lambda, mot vide */ { (print_endline "loop_nom_qualifie : /* Lambda, mot vide */") } + | UL_PT UL_IDENT loop_nom_qualfie { (print_endline "loop_nom_qualifie : PT IDENT loop_nom_qualifie") } + +loop_etat : /* Lambda, mot vide */ { (print_endline "loop_etat : /* Lambda, mot vide */") } + | etat loop_etat { (print_endline "loop_etat : etat loop_etat") } + +loop_region : /* Lambda, mot vide */ { (print_endline "loop_region : /* Lambda, mot vide */") } + | region loop_region { (print_endline "loop_region : region loop_region") } + +option_starts : /* Lambda, mot vide */ { (print_endline "option_starts : /* Lambda, mot vide */") } + | UL_STARTS { (print_endline "option_starts : STARTS") } + +option_ends : /* Lambda, mot vide */ { (print_endline "option_ends : /* Lambda, mot vide */") } + | UL_ENDS { (print_endline "option_ends : ENDS") } + +option_regions : /* Lambda, mot vide */ { (print_endline "option_regions : /* Lambda, mot vide */") } + | UL_ACCOUV region loop_region UL_ACCFER { (print_endline "option_regions : ACCOUV region loop_region ACCFER") } + +%% \ No newline at end of file diff --git a/BE_2020_2021/ascendant/dune b/BE_2020_2021/ascendant/dune new file mode 100755 index 0000000..0cfeb05 --- /dev/null +++ b/BE_2020_2021/ascendant/dune @@ -0,0 +1,7 @@ +(ocamllex Lexer) + +(menhir + (modules Parser)) + +(executable + (name MainMachine)) diff --git a/BE_2020_2021/ascendant/dune-project b/BE_2020_2021/ascendant/dune-project new file mode 100755 index 0000000..192d77f --- /dev/null +++ b/BE_2020_2021/ascendant/dune-project @@ -0,0 +1,2 @@ +(lang dune 2.9) +(using menhir 2.1) diff --git a/BE_2020_2021/descendant/MainMachine.ml b/BE_2020_2021/descendant/MainMachine.ml new file mode 100755 index 0000000..798c71c --- /dev/null +++ b/BE_2020_2021/descendant/MainMachine.ml @@ -0,0 +1,25 @@ +open Tokens +open Scanner +open Parser + +(* main : unit -> unit *) +(* Analyse le contenu d'un fichier passé en paramètre ou l'entrée standard si aucun fichier n'est donné *) +(* Affiche OK si l'analyse syntaxique c'est bien passée et KO sinon *) +let main () = + let cin = + if Array.length Sys.argv > 1 then + open_in Sys.argv.(1) + else + stdin + in + let lexbuf = Lexing.from_channel cin in + let tokens = (scanner lexbuf) in + (print_endline ("Résultat de l'analyse lexicale : " ^ (string_of_stream tokens))); + (print_endline "Analyse syntaxique par descente récursive, règles appliquées :"); + (match (parseM tokens) + with + | Success [UL_FIN] -> print_endline "Succés" + | _ -> print_endline "Echec") +;; + +main();; diff --git a/BE_2020_2021/descendant/Parser.ml b/BE_2020_2021/descendant/Parser.ml new file mode 100755 index 0000000..7e90c6e --- /dev/null +++ b/BE_2020_2021/descendant/Parser.ml @@ -0,0 +1,239 @@ +open Tokens + +(* Type du résultat d'une analyse syntaxique *) +type parseResult = + | Success of inputStream + | Failure +;; + +(* accept : token -> inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien le token attendu *) +(* et avance dans l'analyse si c'est le cas *) +let accept expected stream = + match (peekAtFirstToken stream) with + | token when (token = expected) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptIdent : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un identifiant *) +(* et avance dans l'analyse si c'est le cas *) +let acceptIdent stream = + match (peekAtFirstToken stream) with + | (UL_IDENT _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* Définition de la monade qui est composée de : *) +(* - le type de donnée monadique : parseResult *) +(* - la fonction : inject qui construit ce type à partir d'une liste de terminaux *) +(* - la fonction : bind (opérateur >>=) qui combine les fonctions d'analyse. *) + +(* inject inputStream -> parseResult *) +(* Construit le type de la monade à partir d'une liste de terminaux *) +let inject s = Success s;; + +(* bind : 'a m -> ('a -> 'b m) -> 'b m *) +(* bind (opérateur >>=) qui combine les fonctions d'analyse. *) +(* ici on utilise une version spécialisée de bind : + 'b -> inputStream + 'a -> inputStream + m -> parseResult +*) +(* >>= : parseResult -> (inputStream -> parseResult) -> parseResult *) +let (>>=) result f = + match result with + | Success next -> f next + | Failure -> Failure +;; + +(****** Règles LL1 ******) + +(* parseM : inputStream -> parseResult *) +let rec parseM stream = + (print_endline "M"); + (match (peekAtFirstToken stream) with + (* 1. M -> machine ident { SC } *) + | UL_MACHINE -> + inject stream >>= + accept UL_MACHINE >>= + acceptIdent >>= + accept UL_ACCOUV >>= + parseSC >>= + accept UL_ACCFER + (* Failure *) + | _ -> Failure) + +(* parseSC : inputStream -> parseResult *) +and parseSC stream = + (print_endline "SC"); + (match (peekAtFirstToken stream) with + (* 2. SC -> Λ *) + | UL_ACCFER -> + inject stream + (* 3. SC -> C SC *) + | ( UL_EVENT | UL_FROM | UL_REGION ) -> + inject stream >>= + parseC >>= + parseSC + (* Failure *) + | _ -> Failure) + +(* parseC : inputStream -> parseResult *) +and parseC stream = + (print_endline "C"); + (match (peekAtFirstToken stream) with + (* 4. C -> event ident *) + | UL_EVENT -> + inject stream >>= + accept UL_EVENT >>= + acceptIdent + (* 5. C -> from NQ to NQ on ident *) + | UL_FROM -> + inject stream >>= + accept UL_FROM >>= + parseNQ >>= + accept UL_TO >>= + parseNQ >>= + accept UL_ON >>= + acceptIdent + (* 9. C -> R *) + | UL_REGION -> + inject stream >>= + parseR + (* Failure *) + | _ -> Failure) + +(* parseNQ : inputStream -> parseResult *) +and parseNQ stream = + (print_endline "NQ"); + (match (peekAtFirstToken stream) with + (* 6. NQ -> ident SQ *) + | (UL_IDENT _) -> + inject stream >>= + acceptIdent >>= + parseSQ + (* Failure *) + | _ -> Failure) + +(* parseSQ : inputStream -> parseResult *) +and parseSQ stream = + (print_endline "SQ"); + (match (peekAtFirstToken stream) with + (* 7. SQ -> Λ *) + | ( UL_TO | UL_ON ) -> + inject stream + (* 8. SQ -> . ident SQ *) + | UL_PT -> + inject stream >>= + accept UL_PT >>= + acceptIdent >>= + parseSQ + (* Failure *) + | _ -> Failure) + +(* parseR : inputStream -> parseResult *) +and parseR stream = + (print_endline "R"); + (match (peekAtFirstToken stream) with + (* 10. R -> region ident { E SE } *) + | UL_REGION -> + inject stream >>= + accept UL_REGION >>= + acceptIdent >>= + accept UL_ACCOUV >>= + parseE >>= + parseSE >>= + accept UL_ACCFER + (* Failure *) + | _ -> Failure) + +(* parseSE : inputStream -> parseResult *) +and parseSE stream = + (print_endline "SE"); + (match (peekAtFirstToken stream) with + (* 11. SE -> Λ *) + | UL_ACCFER -> + inject stream + (* 12. SE -> E SE *) + | UL_STATE -> + inject stream >>= + parseE >>= + parseSE + (* Failure *) + | _ -> Failure) + +(* parseE : inputStream -> parseResult *) +and parseE stream = + (print_endline "E"); + (match (peekAtFirstToken stream) with + (* 13. E -> state ident ES EE EC *) + | UL_STATE -> + inject stream >>= + accept UL_STATE >>= + acceptIdent >>= + parseES >>= + parseEE >>= + parseEC + (* Failure *) + | _ -> Failure) + +(* parseES : inputStream -> parseResult *) +and parseES stream = + (print_endline "ES"); + (match (peekAtFirstToken stream) with + (* 14. ES -> Λ *) + | ( UL_ENDS | UL_ACCOUV | UL_ACCFER | UL_STATE ) -> + inject stream + (* 15. ES -> starts *) + | UL_STARTS -> + inject stream >>= + accept UL_STARTS + (* Failure *) + | _ -> Failure) + +(* parseEE : inputStream -> parseResult *) +and parseEE stream = + (print_endline "EE"); + (match (peekAtFirstToken stream) with + (* 16. EE -> Λ *) + | ( UL_ACCOUV | UL_ACCFER | UL_STATE ) -> + inject stream + (* 17. EE -> ends *) + | UL_ENDS -> + inject stream >>= + accept UL_ENDS + (* Failure *) + | _ -> Failure) + +(* parseEC : inputStream -> parseResult *) +and parseEC stream = + (print_endline "EC"); + (match (peekAtFirstToken stream) with + (* 18. EC -> Λ *) + | ( UL_ACCFER | UL_STATE ) -> + inject stream + (* 19. EC -> { R SR } *) + | UL_ACCOUV -> + inject stream >>= + accept UL_ACCOUV >>= + parseR >>= + parseSR >>= + accept UL_ACCFER + (* Failure *) + | _ -> Failure) + +(* parseSR : inputStream -> parseResult *) +and parseSR stream = + (print_endline "SR"); + (match (peekAtFirstToken stream) with + (* 20. SR -> Λ *) + | UL_ACCFER -> + inject stream + (* 21. SR -> R SR *) + | UL_REGION -> + inject stream >>= + parseR >>= + parseSR + (* Failure *) + | _ -> Failure) diff --git a/BE_2020_2021/descendant/Scanner.mll b/BE_2020_2021/descendant/Scanner.mll new file mode 100755 index 0000000..49be124 --- /dev/null +++ b/BE_2020_2021/descendant/Scanner.mll @@ -0,0 +1,43 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open Tokens + exception Printf + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaire = + (* Commentaire fin de ligne *) + "#" [^'\n']* + +rule scanner = parse + | ['\n' '\t' ' ']+ { (scanner lexbuf) } + | commentaire { (scanner lexbuf) } + | "machine" { UL_MACHINE::(scanner lexbuf) } + | "." { UL_PT::(scanner lexbuf) } + | "{" { UL_ACCOUV::(scanner lexbuf) } + | "}" { UL_ACCFER::(scanner lexbuf) } + | "to" { UL_TO::(scanner lexbuf) } + | "on" { UL_ON::(scanner lexbuf) } + | "event" { UL_EVENT::(scanner lexbuf) } + | "from" { UL_FROM::(scanner lexbuf) } + | "region" { UL_REGION::(scanner lexbuf) } + | "ends" { UL_ENDS::(scanner lexbuf) } + | "starts" { UL_STARTS::(scanner lexbuf) } + | "state" { UL_STATE::(scanner lexbuf) } + | eof { [UL_FIN] } + | alphabet+ as texte { (UL_IDENT texte)::(scanner lexbuf) } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); (UL_ERREUR::(scanner lexbuf)) } + +{ + +} diff --git a/BE_2020_2021/descendant/Tokens.ml b/BE_2020_2021/descendant/Tokens.ml new file mode 100755 index 0000000..f61c1d5 --- /dev/null +++ b/BE_2020_2021/descendant/Tokens.ml @@ -0,0 +1,68 @@ +open List + +type token = + | UL_ACCOUV + | UL_ACCFER + | UL_PT + | UL_MACHINE + | UL_TO + | UL_ON + | UL_EVENT + | UL_FROM + | UL_REGION + | UL_ENDS + | UL_STARTS + | UL_STATE + | UL_FIN + | UL_IDENT of string + | UL_ERREUR +;; + +type inputStream = token list;; + +(* string_of_token : token -> string *) +(* Converti un token en une chaîne de caractère*) +let string_of_token token = + match token with + | UL_MACHINE -> "machine" + | UL_ACCOUV -> "{" + | UL_ACCFER -> "}" + | UL_PT -> "." + | UL_TO -> "to" + | UL_ON -> "on" + | UL_EVENT -> "event" + | UL_FROM -> "from" + | UL_REGION -> "region" + | UL_ENDS -> "ends" + | UL_STARTS -> "starts" + | UL_STATE -> "state" + | UL_FIN -> "EOF" + | UL_ERREUR -> "Erreur Lexicale" + | UL_IDENT (texte) -> texte +;; + +(* string_of_stream : inputStream -> string *) +(* Converti un inputStream (liste de token) en une chaîne de caractère *) +let string_of_stream stream = + List.fold_right (fun t tq -> (string_of_token t) ^ " " ^ tq ) stream "";; + + +(* peekAtFirstToken : inputStream -> token *) +(* Renvoie le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let peekAtFirstToken stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible d'acceder au premier element d'un inputStream vide" + |t::_ -> t;; + +(* advanceInStream : inputStream -> inputStream *) +(* Consomme le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let advanceInStream stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible de consommer le premier element d'un inputStream vide" + | _::q -> q;; diff --git a/BE_2020_2021/descendant/dune b/BE_2020_2021/descendant/dune new file mode 100755 index 0000000..75a211c --- /dev/null +++ b/BE_2020_2021/descendant/dune @@ -0,0 +1,4 @@ +(ocamllex Scanner) + +(executables + (names MainMachine)) diff --git a/BE_2020_2021/descendant/dune-project b/BE_2020_2021/descendant/dune-project new file mode 100755 index 0000000..c994249 --- /dev/null +++ b/BE_2020_2021/descendant/dune-project @@ -0,0 +1 @@ +(lang dune 2.9) diff --git a/BE_2020_2021/tests/sujet.sml b/BE_2020_2021/tests/sujet.sml new file mode 100755 index 0000000..4a9f545 --- /dev/null +++ b/BE_2020_2021/tests/sujet.sml @@ -0,0 +1,10 @@ +machine lamp { + event switchOn + event switchOff + region bulb { + state Off starts ends + state On + } + from bulb.Off to buld.On on switchOn + from buld.On to buld.Off on SwitchOff +} diff --git a/BE_2020_2021/tests/test-KO-00.sml b/BE_2020_2021/tests/test-KO-00.sml new file mode 100755 index 0000000..2740db5 --- /dev/null +++ b/BE_2020_2021/tests/test-KO-00.sml @@ -0,0 +1 @@ +machine Test { diff --git a/BE_2020_2021/tests/test-OK-00.sml b/BE_2020_2021/tests/test-OK-00.sml new file mode 100755 index 0000000..2ad7244 --- /dev/null +++ b/BE_2020_2021/tests/test-OK-00.sml @@ -0,0 +1,2 @@ +machine Test { +} diff --git a/BE_2021_2022/ascendant/Lexer.mll b/BE_2021_2022/ascendant/Lexer.mll new file mode 100644 index 0000000..c992211 --- /dev/null +++ b/BE_2021_2022/ascendant/Lexer.mll @@ -0,0 +1,55 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open Parser + exception LexicalError + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let entier = ['1' - '9'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaire = + (* Commentaire fin de ligne *) + "#" [^'\n']* + +rule lexer = parse + | ['\n' '\t' ' ']+ { (lexer lexbuf) } + | commentaire { (lexer lexbuf) } + | "model" { UL_MODEL } + | "system" { UL_SYSTEM } + | "block" { UL_BLOCK } + | "flow" { UL_FLOW } + | "from" { UL_FROM } + | "to" { UL_TO } + | "in" { UL_IN } + | "out" { UL_OUT } + | "int" { UL_INT } + | "float" { UL_FLOAT } + | "boolean" { UL_BOOLEAN } + | "{" { UL_ACCOUV } + | "}" { UL_ACCFER } + | "(" { UL_PAROUV } + | ")" { UL_PARFER } + | "[" { UL_CROOUV } + | "]" { UL_CROFER } + | ";" { UL_PTV } + | "," { UL_VIRG } + | ":" { UL_PT2 } + | "." { UL_PT } + | eof { UL_FIN } + | majuscule alphabet* as texte { (UL_IDENT texte) } + | minuscule alphabet* as texte { (UL_PORT texte) } + | entier chiffre* as texte { (UL_ENTIER (int_of_string texte)) } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); raise LexicalError } + +{ + +} diff --git a/BE_2021_2022/ascendant/MainSystem.ml b/BE_2021_2022/ascendant/MainSystem.ml new file mode 100644 index 0000000..69c4f9b --- /dev/null +++ b/BE_2021_2022/ascendant/MainSystem.ml @@ -0,0 +1,52 @@ +open Parser + +(* Fonction d'affichage des unités lexicales et des données qu'elles contiennent *) +let printToken t = + (print_endline + (match t with + | UL_MODEL -> "model" + | UL_SYSTEM -> "system" + | UL_BLOCK -> "block" + | UL_FLOW -> "flow" + | UL_FROM -> "from" + | UL_TO -> "to" + | UL_IN -> "in" + | UL_OUT -> "out" + | UL_INT -> "int" + | UL_FLOAT -> "float" + | UL_BOOLEAN -> "boolean" + | UL_ACCOUV -> "{" + | UL_ACCFER -> "}" + | UL_PAROUV -> "(" + | UL_PARFER -> ")" + | UL_CROOUV -> "[" + | UL_CROFER -> "]" + | UL_PTV -> ";" + | UL_VIRG -> "," + | UL_PT2 -> ":" + | UL_PT -> "." + | UL_IDENT texte -> texte + | UL_PORT texte -> texte + | UL_ENTIER texte -> (string_of_int texte) + | UL_FIN -> "EOF" +));; + +(* Analyse lexicale du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + let token = ref (Lexer.lexer lexbuf) in + while ((!token) != UL_FIN) do + (printToken (!token)); + (token := (Lexer.lexer lexbuf)) + done +else + (print_endline "MainJSON fichier");; + +(* Analyse lexicale, syntaxique et sémantique du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + (Parser.modele Lexer.lexer lexbuf) +else + (print_endline "MainJSON fichier");; diff --git a/BE_2021_2022/ascendant/Parser.mly b/BE_2021_2022/ascendant/Parser.mly new file mode 100644 index 0000000..dec6e96 --- /dev/null +++ b/BE_2021_2022/ascendant/Parser.mly @@ -0,0 +1,88 @@ +%{ + +(* Partie recopiee dans le fichier CaML genere. *) +(* Ouverture de modules exploites dans les actions *) +(* Declarations de types, de constantes, de fonctions, d'exceptions exploites dans les actions *) + +%} + +/* Declaration des unites lexicales et de leur type si une valeur particuliere leur est associee */ + +%token UL_MODEL +%token UL_ACCOUV UL_ACCFER +%token UL_SYSTEM +%token UL_BLOCK +%token UL_FLOW UL_FROM UL_TO +%token UL_IN UL_OUT +%token UL_INT UL_FLOAT UL_BOOLEAN +%token UL_PAROUV UL_PARFER +%token UL_CROOUV UL_CROFER +%token UL_PTV UL_VIRG UL_PT2 UL_PT + +/* Defini le type des donnees associees a l'unite lexicale */ + +%token UL_IDENT +%token UL_PORT +%token UL_ENTIER + +/* Unite lexicale particuliere qui represente la fin du fichier */ + +%token UL_FIN + +/* Type renvoye pour le nom terminal document */ +%type modele + +/* Le non terminal document est l'axiome */ +%start modele + +%% /* Regles de productions */ + +modele : UL_MODEL UL_IDENT UL_ACCOUV loop_element UL_ACCFER UL_FIN { (print_endline "modele : UL_MODEL IDENT { loop_element } UL_FIN ") } + +element : bloc { (print_endline "element : bloc") } + | systeme { (print_endline "element : systeme") } + | flot { (print_endline "element : flot") } + +loop_element : /* Lambda */ { (print_endline "loop_element : /* Lambda */") } + | element loop_element { (print_endline "loop_element : element loop_element") } + +bloc : UL_BLOCK UL_IDENT parametres UL_PTV { (print_endline "bloc : UL_BLOCK UL_IDENT parametres UL_PTV") } + +systeme : UL_SYSTEM UL_IDENT parametres UL_ACCOUV loop_element UL_ACCFER { (print_endline "systeme : UL_SYSTEM UL_IDENT parametres UL_ACCOUV loop_element UL_ACCFER") } + +parametres : UL_PAROUV port loop_port UL_PARFER { (print_endline "parametres : UL_PAROUV port loop_port UL_PARFER") } + +loop_port : /* Lambda */ { (print_endline "loop_port : /* Lambda */") } + | UL_VIRG port loop_port { (print_endline "loop_port : UL_VIRG port loop_port") } + +port : UL_PORT UL_PT2 in_or_out type_ { (print_endline "port : UL_PORT UL_PT2 in_or_out type_") } + +in_or_out : UL_IN { (print_endline "in_or_out : UL_IN") } + | UL_OUT { (print_endline "in_or_out : UL_OUT") } + +type_ : select_type option_entiers { (print_endline "type_ : select_type option_entiers") } + +select_type : UL_INT { (print_endline "select_type : UL_INT") } + | UL_FLOAT { (print_endline "select_type : UL_FLOAT") } + | UL_BOOLEAN { (print_endline "select_type : UL_BOOLEAN") } + +option_entiers : /* Lambda */ { (print_endline "option_entiers : /* Lambda */") } + | UL_CROOUV UL_ENTIER loop_entier UL_CROFER { (print_endline "option_entiers : UL_CROOUV UL_ENTIER loop_entier UL_CROFER") } + +loop_entier : /* Lambda */ { (print_endline "loop_entier : /* Lambda */") } + | UL_VIRG UL_ENTIER loop_entier { (print_endline "loop_entier : UL_VIRG UL_ENTIER loop_entier") } + +flot : UL_FLOW UL_PORT UL_FROM option_ident UL_PORT UL_TO option_loop_ident_port UL_PTV { (print_endline "flot : UL_FLOW UL_PORT UL_FROM option_ident UL_PORT UL_TO option_loop_ident_port UL_PTV") } + +option_ident : /* Lambda */ { (print_endline "option_ident : /* Lambda */") } + | UL_IDENT UL_PT { (print_endline "option_ident : UL_IDENT UL_PT") } + +ident_port : option_ident UL_PORT { (print_endline "ident_port : option_ident UL_PORT") } + +loop_ident_port : /* Lambda */ { (print_endline "loop_ident_port : /* Lambda */") } + | UL_VIRG ident_port loop_ident_port { (print_endline "loop_ident_port : UL_IDENT UL_PT") } + +option_loop_ident_port : /* Lambda */ { (print_endline "option_loop_ident_port : /* Lambda */") } + | ident_port loop_ident_port { (print_endline "option_loop_ident_port : ident_port loop_ident_port") } + +%% diff --git a/BE_2021_2022/ascendant/dune b/BE_2021_2022/ascendant/dune new file mode 100644 index 0000000..6158748 --- /dev/null +++ b/BE_2021_2022/ascendant/dune @@ -0,0 +1,7 @@ +(ocamllex Lexer) + +(menhir + (modules Parser)) + +(executable + (name MainSystem)) diff --git a/BE_2021_2022/ascendant/dune-project b/BE_2021_2022/ascendant/dune-project new file mode 100644 index 0000000..192d77f --- /dev/null +++ b/BE_2021_2022/ascendant/dune-project @@ -0,0 +1,2 @@ +(lang dune 2.9) +(using menhir 2.1) diff --git a/BE_2021_2022/descendant/MainSystem.ml b/BE_2021_2022/descendant/MainSystem.ml new file mode 100644 index 0000000..8a4ee02 --- /dev/null +++ b/BE_2021_2022/descendant/MainSystem.ml @@ -0,0 +1,25 @@ +open Tokens +open Scanner +open Parser + +(* main : unit -> unit *) +(* Analyse le contenu d'un fichier passé en paramètre ou l'entrée standard si aucun fichier n'est donné *) +(* Affiche OK si l'analyse syntaxique c'est bien passée et KO sinon *) +let main () = + let cin = + if Array.length Sys.argv > 1 then + open_in Sys.argv.(1) + else + stdin + in + let lexbuf = Lexing.from_channel cin in + let tokens = (scanner lexbuf) in + (print_endline ("Résultat de l'analyse lexicale :" ^ (string_of_stream tokens))); + (print_endline "Analyse syntaxique par descente récursive, règles appliquées :"); + (match (parseR tokens) + with + | Success [UL_FIN] -> print_endline "Succés" + | _ -> print_endline "Echec") +;; + +main();; diff --git a/BE_2021_2022/descendant/Parser.ml b/BE_2021_2022/descendant/Parser.ml new file mode 100644 index 0000000..8cfbbc1 --- /dev/null +++ b/BE_2021_2022/descendant/Parser.ml @@ -0,0 +1,303 @@ +open Tokens + +(* Type du résultat d'une analyse syntaxique *) +type parseResult = + | Success of inputStream + | Failure +;; + +(* accept : token -> inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien le token attendu *) +(* et avance dans l'analyse si c'est le cas *) +let accept expected stream = + match (peekAtFirstToken stream) with + | token when (token = expected) -> + (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptIdent : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un identifiant *) +(* et avance dans l'analyse si c'est le cas *) +let acceptIdent stream = + match (peekAtFirstToken stream) with + | (UL_IDENT _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptPort : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un port *) +(* et avance dans l'analyse si c'est le cas *) +let acceptPort stream = + match (peekAtFirstToken stream) with + | (UL_PORT _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptEntier : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un entier *) +(* et avance dans l'analyse si c'est le cas *) +let acceptEntier stream = + match (peekAtFirstToken stream) with + | (UL_ENTIER _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* Définition de la monade qui est composée de : *) +(* - le type de donnée monadique : parseResult *) +(* - la fonction : inject qui construit ce type à partir d'une liste de terminaux *) +(* - la fonction : bind (opérateur >>=) qui combine les fonctions d'analyse. *) + +(* inject inputStream -> parseResult *) +(* Construit le type de la monade à partir d'une liste de terminaux *) +let inject s = Success s;; + +(* bind : 'a m -> ('a -> 'b m) -> 'b m *) +(* bind (opérateur >>=) qui combine les fonctions d'analyse. *) +(* ici on utilise une version spécialisée de bind : + 'b -> inputStream + 'a -> inputStream + m -> parseResult +*) +(* >>= : parseResult -> (inputStream -> parseResult) -> parseResult *) +let (>>=) result f = + match result with + | Success next -> f next + | Failure -> Failure +;; + + +(* parseR : inputStream -> parseResult *) +(* Analyse du non terminal Programme *) +let rec parseR stream = + (print_string "R"); + (match (peekAtFirstToken stream) with + (* 1. R -> model Ident { SE } *) + | UL_MODEL -> + inject stream >>= + accept UL_MODEL >>= + acceptIdent >>= + accept UL_ACCOUV >>= + parseSE >>= + accept UL_ACCFER + (* Failure *) + | _ -> Failure) + +(* parseSE : inputStream -> parseResult *) +and parseSE stream = + (print_endline "SE"); + (match (peekAtFirstToken stream) with + (* 2. SE -> Λ *) + | UL_ACCFER -> + inject stream + (* 3. SE -> E SE *) + | ( UL_BLOCK | UL_SYSTEM | UL_FLOW ) -> + inject stream >>= + parseE >>= + parseSE + (* Failure *) + | _ -> Failure) + +(* parseE : inputStream -> parseResult *) +and parseE stream = + (print_endline "E"); + (match (peekAtFirstToken stream) with + (* 4. E -> block Ident P ; *) + | UL_BLOCK -> + inject stream >>= + accept UL_BLOCK >>= + acceptIdent >>= + parseP >>= + accept UL_PTV + (* 5. E -> system Ident P { SE } *) + | UL_SYSTEM -> + inject stream >>= + accept UL_SYSTEM >>= + acceptIdent >>= + parseP >>= + accept UL_ACCOUV >>= + parseSE >>= + accept UL_ACCFER + (* 6. E -> flow ident from NQ to LN ; *) + | UL_FLOW -> + inject stream >>= + accept UL_FLOW >>= + acceptPort >>= + accept UL_FROM >>= + parseNQ >>= + accept UL_TO >>= + parseLN >>= + accept UL_PTV + (* Failure *) + | _ -> Failure) + +(* parseNQ : inputStream -> parseResult *) +and parseNQ stream = + (print_endline "NQ"); + (match (peekAtFirstToken stream) with + (* 7. NQ -> ident *) + | (UL_PORT _) -> + inject stream >>= + acceptPort + (* 8. NQ -> Ident . ident *) + | (UL_IDENT _) -> + inject stream >>= + acceptIdent >>= + accept UL_PT >>= + acceptPort + (* Failure *) + | _ -> Failure) + +(* parseLN : inputStream -> parseResult *) +and parseLN stream = + (print_endline "LN"); + (match (peekAtFirstToken stream) with + (* 9. LN -> Λ *) + | UL_PTV -> + inject stream + (* 10. LN -> NQ SN *) + | ( (UL_IDENT _) | (UL_PORT _) ) -> + inject stream >>= + parseNQ >>= + parseSN + (* Failure *) + | _ -> Failure) + +(* parseSN : inputStream -> parseResult *) +and parseSN stream = + (print_endline "SN"); + (match (peekAtFirstToken stream) with + (* 11. SN -> Λ *) + | UL_PTV -> + inject stream + (* 12. LN -> , NQ SN *) + | UL_VIRG -> + inject stream >>= + accept UL_VIRG >>= + parseNQ >>= + parseSN + (* Failure *) + | _ -> Failure) + +(* parseP : inputStream -> parseResult *) +and parseP stream = + (print_endline "P"); + (match (peekAtFirstToken stream) with + (* 13. P -> ( LP ) *) + | UL_PAROUV -> + inject stream >>= + accept UL_PAROUV >>= + parseLP >>= + accept UL_PARFER + (* Failure *) + | _ -> Failure) + +(* parseLP : inputStream -> parseResult *) +and parseLP stream = + (print_endline "LP"); + (match (peekAtFirstToken stream) with + (* 14. LP -> DP SP *) + | (UL_PORT _) -> + inject stream >>= + parseDP >>= + parseSP + (* Failure *) + | _ -> Failure) + +(* parseSP : inputStream -> parseResult *) +and parseSP stream = + (print_endline "SP"); + (match (peekAtFirstToken stream) with + (* 15. SP -> Λ *) + | UL_PARFER -> + inject stream + (* 16. LN -> , DP SP *) + | UL_VIRG -> + inject stream >>= + accept UL_VIRG >>= + parseDP >>= + parseSP + (* Failure *) + | _ -> Failure) + +(* parseDP : inputStream -> parseResult *) +and parseDP stream = + (print_endline "DP"); + (match (peekAtFirstToken stream) with + (* 17. LP -> ident : M T OT *) + | (UL_PORT _) -> + inject stream >>= + acceptPort >>= + accept UL_PT2 >>= + parseM >>= + parseT >>= + parseOT + (* Failure *) + | _ -> Failure) + +(* parseM : inputStream -> parseResult *) +and parseM stream = + (print_endline "M"); + (match (peekAtFirstToken stream) with + (* 18. M -> in *) + | UL_IN -> + inject stream >>= + accept UL_IN + (* 19. M -> out *) + | UL_OUT -> + inject stream >>= + accept UL_OUT + (* Failure *) + | _ -> Failure) + +(* parseT : inputStream -> parseResult *) +and parseT stream = + (print_endline "T"); + (match (peekAtFirstToken stream) with + (* 20. T -> int *) + | UL_INT -> + inject stream >>= + accept UL_INT + (* 21. M -> float *) + | UL_FLOAT -> + inject stream >>= + accept UL_FLOAT + (* 22. M -> boolean *) + | UL_BOOLEAN -> + inject stream >>= + accept UL_BOOLEAN + (* Failure *) + | _ -> Failure) + +(* parseOT : inputStream -> parseResult *) +and parseOT stream = + (print_endline "OT"); + (match (peekAtFirstToken stream) with + (* 23. OT -> Λ *) + | ( UL_VIRG | UL_PARFER ) -> + inject stream + (* 24. OT -> [ entier SV ] *) + | UL_CROOUV -> + inject stream >>= + accept UL_CROOUV >>= + acceptEntier >>= + parseSV >>= + accept UL_CROFER + (* Failure *) + | _ -> Failure) + +(* parseSV : inputStream -> parseResult *) +and parseSV stream = + (print_endline "SV"); + (match (peekAtFirstToken stream) with + (* 25. OT -> Λ *) + | UL_CROFER -> + inject stream + (* 26. OT -> , entier SV *) + | UL_VIRG -> + inject stream >>= + accept UL_VIRG >>= + acceptEntier >>= + parseSV + (* Failure *) + | _ -> Failure) diff --git a/BE_2021_2022/descendant/Scanner.mll b/BE_2021_2022/descendant/Scanner.mll new file mode 100644 index 0000000..9b0decd --- /dev/null +++ b/BE_2021_2022/descendant/Scanner.mll @@ -0,0 +1,55 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open Tokens + exception Printf + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let entier = ['1' - '9'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaire = + (* Commentaire fin de ligne *) + "#" [^'\n']* + +rule scanner = parse + | ['\n' '\t' ' ']+ { (scanner lexbuf) } + | commentaire { (scanner lexbuf) } + | "model" { UL_MODEL::(scanner lexbuf) } + | "system" { UL_SYSTEM::(scanner lexbuf) } + | "block" { UL_BLOCK::(scanner lexbuf) } + | "flow" { UL_FLOW::(scanner lexbuf) } + | "from" { UL_FROM::(scanner lexbuf) } + | "to" { UL_TO::(scanner lexbuf) } + | "in" { UL_IN::(scanner lexbuf) } + | "out" { UL_OUT::(scanner lexbuf) } + | "int" { UL_INT::(scanner lexbuf) } + | "float" { UL_FLOAT::(scanner lexbuf) } + | "boolean" { UL_BOOLEAN::(scanner lexbuf) } + | "{" { UL_ACCOUV::(scanner lexbuf) } + | "}" { UL_ACCFER::(scanner lexbuf) } + | "(" { UL_PAROUV::(scanner lexbuf) } + | ")" { UL_PARFER::(scanner lexbuf) } + | "[" { UL_CROOUV::(scanner lexbuf) } + | "]" { UL_CROFER::(scanner lexbuf) } + | ";" { UL_PTV::(scanner lexbuf) } + | "," { UL_VIRG::(scanner lexbuf) } + | ":" { UL_PT2::(scanner lexbuf) } + | "." { UL_PT::(scanner lexbuf) } + | majuscule alphabet* as texte { (UL_IDENT texte)::(scanner lexbuf) } + | minuscule alphabet* as texte { (UL_PORT texte)::(scanner lexbuf) } + | entier chiffre* as texte { (UL_ENTIER (int_of_string texte))::(scanner lexbuf) } + | eof { [UL_FIN] } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); (UL_ERREUR::(scanner lexbuf)) } + +{ + +} diff --git a/BE_2021_2022/descendant/Tokens.ml b/BE_2021_2022/descendant/Tokens.ml new file mode 100644 index 0000000..0af51dd --- /dev/null +++ b/BE_2021_2022/descendant/Tokens.ml @@ -0,0 +1,88 @@ +open List + +type token = + | UL_MODEL + | UL_SYSTEM + | UL_BLOCK + | UL_FLOW + | UL_FROM + | UL_TO + | UL_IN + | UL_OUT + | UL_INT + | UL_FLOAT + | UL_BOOLEAN + | UL_ACCOUV + | UL_ACCFER + | UL_PAROUV + | UL_PARFER + | UL_CROOUV + | UL_CROFER + | UL_PTV + | UL_VIRG + | UL_PT2 + | UL_PT + | UL_IDENT of string + | UL_PORT of string + | UL_ENTIER of int + | UL_FIN + | UL_ERREUR;; + +type inputStream = token list;; + +(* string_of_token : token -> string *) +(* Converti un token en une chaîne de caractère*) +let string_of_token token = + match token with + | UL_MODEL -> "model" + | UL_SYSTEM -> "system" + | UL_BLOCK -> "block" + | UL_FLOW -> "flow" + | UL_FROM -> "from" + | UL_TO -> "to" + | UL_IN -> "in" + | UL_OUT -> "out" + | UL_INT -> "int" + | UL_FLOAT -> "float" + | UL_BOOLEAN -> "boolean" + | UL_ACCOUV -> "{" + | UL_ACCFER -> "}" + | UL_PAROUV -> "(" + | UL_PARFER -> ")" + | UL_CROOUV -> "[" + | UL_CROFER -> "]" + | UL_PTV -> ";" + | UL_VIRG -> "," + | UL_PT2 -> ":" + | UL_PT -> "." + | UL_IDENT texte -> texte + | UL_PORT texte -> texte + | UL_ENTIER texte -> (string_of_int texte) + | UL_FIN -> "EOF" + | UL_ERREUR -> "Erreur Lexicale";; + +(* string_of_stream : inputStream -> string *) +(* Converti un inputStream (liste de token) en une chaîne de caractère *) +let string_of_stream stream = + List.fold_right (fun t tq -> (string_of_token t) ^ " " ^ tq ) stream "";; + + +(* peekAtFirstToken : inputStream -> token *) +(* Renvoie le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let peekAtFirstToken stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible d'acceder au premier element d'un inputStream vide" + |t::_ -> t;; + +(* advanceInStream : inputStream -> inputStream *) +(* Consomme le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let advanceInStream stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible de consommer le premier element d'un inputStream vide" + | _::q -> q;; diff --git a/BE_2021_2022/descendant/dune b/BE_2021_2022/descendant/dune new file mode 100644 index 0000000..5fc66e2 --- /dev/null +++ b/BE_2021_2022/descendant/dune @@ -0,0 +1,4 @@ +(ocamllex Scanner) + +(executables + (names MainSystem)) diff --git a/BE_2021_2022/descendant/dune-project b/BE_2021_2022/descendant/dune-project new file mode 100644 index 0000000..c994249 --- /dev/null +++ b/BE_2021_2022/descendant/dune-project @@ -0,0 +1 @@ +(lang dune 2.9) diff --git a/BE_2021_2022/tests/sujet.sdl b/BE_2021_2022/tests/sujet.sdl new file mode 100644 index 0000000..05f7d04 --- /dev/null +++ b/BE_2021_2022/tests/sujet.sdl @@ -0,0 +1,11 @@ +model S { + flow f from Ba.ra to HS.pa, HS.pb; + block Ba(pa : in float, pb : in float, ra : out float [ 2 ] ); + system HS(pa : in float [ 2 ], ra : out float, pb : in float [ 2 ] , rb : out float [ 2 ] ) { + block Bb(ra : out float, pa : in float); + flow fa from pa to Bb.pa; + flow fb from pb to rb; + } + flow fb from HS.ra to Ba.pa, Ba.pb; + flow fc from HS.rb to; +} diff --git a/TP1/dune b/TP1/dune new file mode 100755 index 0000000..3efe66f --- /dev/null +++ b/TP1/dune @@ -0,0 +1,5 @@ +(ocamllex lexerJava) + +(executable + (modes byte exe) + (name mainJava)) diff --git a/TP1/dune-project b/TP1/dune-project new file mode 100755 index 0000000..e563d7e --- /dev/null +++ b/TP1/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) + +(formatting disabled) diff --git a/TP1/lexerJava.mll b/TP1/lexerJava.mll new file mode 100755 index 0000000..aa68186 --- /dev/null +++ b/TP1/lexerJava.mll @@ -0,0 +1,95 @@ +{ + + open TokenJava +(* open String *) +(* open Str *) + exception LexicalError + +} + +(* Macro-definitions *) +let minuscule = ['a'-'z'] +let javaLetter = minuscule | '_' +let majuscule = ['A'-'Z'] +let chiffre = ['0'-'9'] +let hexa = chiffre | ['a'-'f'] | ['A'-'F'] +let octa = ['0'-'7'] +let alphabet = minuscule | majuscule +let alphanum = alphabet | chiffre | '_' +let commentaireBloc = "/*" [^'*']* ('*' [^'/'] [^'*']*)* "*/" +let commentaireLigne = "//" [^'\n']* '\n' + +(* Analyseur lexical : expression reguliere { action CaML } *) +rule lexer = parse +(* Espace, tabulation, passage a ligne, etc : consommes par l'analyse lexicale *) + | ['\n' '\t' ' ']+ { lexer lexbuf } +(* Commentaires consommés par l'analyse lexicale *) + | commentaireBloc { lexer lexbuf } + | commentaireLigne { lexer lexbuf } +(* Structures de blocs *) + | "(" { PAROUV } + | ")" { PARFER } + | "[" { CROOUV } + | "]" { CROFER } + | "{" { ACCOUV } + | "}" { ACCFER } +(* Separateurs *) + | "," { VIRG } + | ";" { PTVIRG } +(* Operateurs booleens *) + | "||" { OPOU } + | "&&" { OPET } + | "!" { OPNON } +(* Operateurs comparaisons *) + | "==" { OPEG } + | "!=" { OPNONEG } + | "<=" { OPSUPEG } + | "<" { OPSUP } + | ">=" { OPINFEG } + | ">" { OPINF } +(* Operateurs arithmetiques *) + | "+" { OPPLUS } + | "-" { OPMOINS } + | "*" { OPMULT } + | "/" { OPDIV } + | "%" { OPMOD } + | "." { OPPT } + | "=" { ASSIGN } + | "new" { NOUVEAU } +(* Mots cles : types *) + | "bool" { BOOL } + | "char" { CHAR } + | "float" { FLOAT } + | "int" { INT } + | "String" { STRING } + | "void" { VOID } +(* Mots cles : instructions *) + | "while" { TANTQUE } + | "if" { SI } + | "else" { SINON } + | "return" { RETOUR } +(* Mots cles : constantes *) + | "true" { (BOOLEEN true) } + | "false" { (BOOLEEN false) } + | "null" { VIDE } +(* Nombres entiers : *) + | ( '0' | (['1' - '9'](chiffre | '_')*) ) as texte { (ENTIER (int_of_string texte)) } + | ( '0'('b'|'B') (chiffre | '_')* ) as texte { (BINAIRE (int_of_string texte)) } + | ( '0'('x'|'X') (hexa | '_')* ) as texte { (HEXA (int_of_string texte)) } + | ( '0'* (octa | '_')* ) as texte { (OCTA (int_of_string ("0o" ^ texte))) } +(* Nombres flottants : *) + | ['+''-']? ( chiffre+ | chiffre+ '.' chiffre+ | '.' chiffre+ | chiffre+ '.' ) (['e''E'] ['+''-']? chiffre+ )? as texte { (FLOTTANT (float_of_string texte)) } +(* Caracteres : *) + | "'" _ "'" as texte { CARACTERE texte.[1] } + | "'" '\\' _* "'" as texte { print_endline texte; CARACTERE (char_of_int (int_of_string (String.sub texte 2 ((String.length texte) - 3)))) } +(* Chaines de caracteres : A COMPLETER *) + | '"' _* '"' as texte { CHAINE texte } +(* Identificateurs *) + | majuscule alphanum* as texte { TYPEIDENT texte } + | javaLetter alphanum* as texte { IDENT texte } + | eof { FIN } + | _ { raise LexicalError } + +{ + +} diff --git a/TP1/mainJava.ml b/TP1/mainJava.ml new file mode 100755 index 0000000..71e8ae3 --- /dev/null +++ b/TP1/mainJava.ml @@ -0,0 +1,12 @@ +open TokenJava;; + +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + let token = ref (LexerJava.lexer lexbuf) in + while ((!token) != FIN) do + (printToken (!token)); + (token := (LexerJava.lexer lexbuf)) + done +else + (print_endline "mainJava.exe fichier") diff --git a/TP1/tests/exemple-complique.java b/TP1/tests/exemple-complique.java new file mode 100755 index 0000000..f8d9249 --- /dev/null +++ b/TP1/tests/exemple-complique.java @@ -0,0 +1,49 @@ + +/* Cet exemple respecte la syntaxe (grammaire) de microjava, avec des + * commentaires, des cha�nes complexes, des r�els bizarres... + * Les constructions qui ne sont pas trait + * Ce programme est s�mantiquement faux (typage en particulier) + */ + +/* class Point { + private int x; + private int y; + + private String toto; + + // rien { + public int get_x () */ +{ return x; } +// public void set_x (int _x) +{ x = _x; } + +// private void essai_string () + { + toto = "machin avec des espaces et des \" quotes +et multiligne avec echappement \n meme a la fin \\"; foo(); "et une autre chaine"; + x = 3.14 + .14 + 3. + 14e-1 + .3e1; + y = 'a' + '\33' + 0x2A; + } +} + +/* ghjd /* ****/ +/* class PointColore extends Point { + public int c; + public int get_c () */ + { return c*2; } +/* } */ +/***** +class PointColore extends Point **g + // dfgkhdk *f ** */ + +/* public class Exemple { + public static void main (String[] argv) */ + { + int x; + bool b; + b = true; + if (b) { + x = 2*x + 3; + } + } +// } diff --git a/TP1/tests/exemple-simple.java b/TP1/tests/exemple-simple.java new file mode 100755 index 0000000..2a6a902 --- /dev/null +++ b/TP1/tests/exemple-simple.java @@ -0,0 +1,32 @@ + +// Note: ce fichier ne respecte pas la *grammaire* de micro-java +// Il ne fait qu'enumerer les tokens de la grammaire. + +// mot clefs +// class extends private public static main + +// types +int void float bool char String + +// structures de controle +if else while return + +// instructions +new null + +// operateurs +< > >= <= == != ++ - / * % && || ! = . + +// parentheses +( [ { } ] ) + +// separateurs +, ; + +// constantes +true false 0 245 1_234_567 0b1101 0B1_0100_1100 077 01_345 0xFF 0X1_FF00_1234 'a' '(' '?' '\'' '\\' 567.34 +1e-5 -.12 1.5e-4 2. +"bonjour" + +// noms +x toto Point diff --git a/TP1/tests/exemple-tres-simple.java b/TP1/tests/exemple-tres-simple.java new file mode 100755 index 0000000..b434f6d --- /dev/null +++ b/TP1/tests/exemple-tres-simple.java @@ -0,0 +1,3 @@ +, /* test */ int while // ceci est un autre test +" te \" st " +123 diff --git a/TP1/tests/exemple.java b/TP1/tests/exemple.java new file mode 100755 index 0000000..ace6482 --- /dev/null +++ b/TP1/tests/exemple.java @@ -0,0 +1,2 @@ +453 while 45, 4, 8 +int 4 int while , 8 diff --git a/TP1/tests/test.java b/TP1/tests/test.java new file mode 100755 index 0000000..e58c6ab --- /dev/null +++ b/TP1/tests/test.java @@ -0,0 +1,11 @@ +// commentaire ligne +/* + commentaire + bloc +*/ +a = 4 +/*aaa*/ +index + 000123 +{ + bonjour = 3 +} \ No newline at end of file diff --git a/TP1/tokenJava.ml b/TP1/tokenJava.ml new file mode 100755 index 0000000..b1b54e5 --- /dev/null +++ b/TP1/tokenJava.ml @@ -0,0 +1,121 @@ +open Char + +(* Type déclarent les différentes unités lexicales possibles *) + +type token = +(* Identificateurs *) + | IDENT of string + | TYPEIDENT of string +(* Mots cles : types *) + | INT + | FLOAT + | BOOL + | CHAR + | VOID + | STRING +(* Structure de blocs *) + | ACCOUV + | ACCFER + | PAROUV + | PARFER + | CROOUV + | CROFER +(* Separateurs *) + | PTVIRG + | VIRG +(* Mots cles : Instructions *) + | SI + | SINON + | TANTQUE + | RETOUR +(* Valeurs *) + | ENTIER of int + | BINAIRE of int + | HEXA of int + | OCTA of int + | FLOTTANT of float + | BOOLEEN of bool + | CARACTERE of char + | CHAINE of string + | VIDE +(* Operateurs *) + | NOUVEAU + | ASSIGN + | OPPT +(* Comparaison *) + | OPNONEG + | OPEG + | OPSUPEG + | OPINFEG + | OPSUP + | OPINF +(* Booleen *) + | OPOU + | OPET + | OPNON +(* Arithmetique *) + | OPPLUS + | OPMOINS + | OPMULT + | OPDIV + | OPMOD +(* Fin de texte *) + | FIN ;; + +let printToken t = + (print_endline + (match t with +(* Structure de blocs *) + | PAROUV -> "bloc : (" + | PARFER -> "bloc : )" + | CROOUV -> "bloc : [" + | CROFER -> "bloc : ]" + | ACCOUV -> "bloc : {" + | ACCFER -> "bloc : }" +(* Separateurs *) + | VIRG -> "separateur : ," + | PTVIRG -> "separateur : ;" +(* Operateurs *) + | OPEG -> "operateur : ==" + | OPNONEG -> "operateur : !=" + | OPINFEG -> "operateur : >=" + | OPINF -> "operateur : >" + | OPSUPEG -> "operateur : <=" + | OPSUP -> "operateur : <" + | OPET -> "operateur : &&" + | OPOU -> "operateur : ||" + | OPNON -> "operateur : !" + | OPPLUS -> "operateur : +" + | OPMOINS -> "operateur : -" + | OPMULT -> "operateur : *" + | OPDIV -> "operateur : /" + | OPMOD -> "operateur : %" + | ASSIGN -> "operateur : =" + | OPPT -> "operateur : ." + | NOUVEAU -> "operateur : new" +(* Mots cles : Instructions *) + | TANTQUE -> "mot-cle : while" + | SI -> "mot-cle : if" + | SINON -> "mot-cle : else" + | RETOUR -> "mot-cle : return" +(* Mots cles : Types *) + | BOOL -> "type : boolean" + | CHAR -> "type : char" + | FLOAT -> "type : float" + | INT -> "type : int" + | STRING -> "type : String" + | VOID -> "type : void" +(* Valeurs *) + | BOOLEEN b -> "booleen : " ^ (if b then "true" else "false") + | CARACTERE c -> "caractere : '" ^ (escaped c) ^ "'" + | CHAINE s -> "chaine : " ^ s + | ENTIER n -> "entier : " ^ string_of_int n + | HEXA n -> "hexa : " ^ string_of_int n + | OCTA n -> "octa : " ^ string_of_int n + | BINAIRE n -> "binaire : " ^ string_of_int n + | FLOTTANT f -> "flottant : " ^ string_of_float f + | VIDE -> "null" +(* Identificateurs *) + | IDENT n -> "identificateur : " ^ n + | TYPEIDENT t -> "identificateur de type : " ^ t + | _ -> "TBC"));; diff --git a/TP1/tokenJava.mli b/TP1/tokenJava.mli new file mode 100755 index 0000000..d2c188f --- /dev/null +++ b/TP1/tokenJava.mli @@ -0,0 +1,65 @@ +(* Type déclarent les différentes unités lexicales possibles *) + +type token = +(* Identificateurs *) + | IDENT of string + | TYPEIDENT of string +(* Mots cles : types *) + | INT + | FLOAT + | BOOL + | CHAR + | VOID + | STRING +(* Structure de blocs *) + | ACCOUV + | ACCFER + | PAROUV + | PARFER + | CROOUV + | CROFER +(* Separateurs *) + | PTVIRG + | VIRG +(* Mots cles : Instructions *) + | SI + | SINON + | TANTQUE + | RETOUR +(* Valeurs *) + | ENTIER of int + | BINAIRE of int + | HEXA of int + | OCTA of int + | FLOTTANT of float + | BOOLEEN of bool + | CARACTERE of char + | CHAINE of string + | VIDE +(* Operateurs *) + | NOUVEAU + | ASSIGN + | OPPT +(* Comparaison *) + | OPNONEG + | OPEG + | OPSUPEG + | OPINFEG + | OPSUP + | OPINF +(* Booleen *) + | OPOU + | OPET + | OPNON +(* Arithmetique *) + | OPPLUS + | OPMOINS + | OPMULT + | OPDIV + | OPMOD +(* Fin de texte *) + | FIN ;; + + +(* Fonction d'affichage d'une unité lexicale *) +val printToken : token -> unit;; diff --git a/TP2/dune b/TP2/dune new file mode 100755 index 0000000..d6a0a0a --- /dev/null +++ b/TP2/dune @@ -0,0 +1,7 @@ +(ocamllex lexerJava) + +(menhir + (modules parserJava)) + +(executable + (name mainJava)) diff --git a/TP2/dune-project b/TP2/dune-project new file mode 100755 index 0000000..8aeefc5 --- /dev/null +++ b/TP2/dune-project @@ -0,0 +1,5 @@ +(lang dune 2.0) + +(using menhir 2.0) + +(formatting disabled) diff --git a/TP2/lexerJava.mll b/TP2/lexerJava.mll new file mode 100755 index 0000000..3e552b4 --- /dev/null +++ b/TP2/lexerJava.mll @@ -0,0 +1,82 @@ +{ + +(* Partie recopiée dans le fichier CaML généré. *) +(* Ouverture de modules exploités dans les actions *) +(* Déclarations de types, de constantes, de fonctions, d'exceptions exploités dans les actions *) + + open ParserJava + exception LexicalError + +} + +(* Déclaration d'expressions régulières exploitées par la suite *) +let chiffre = ['0' - '9'] +let binaire = ('0' | '1') +let octal = ['0' - '7'] +let hexadecimal = chiffre | ['A' - 'F'] +let minuscule = ['a' - 'z'] +let majuscule = ['A' - 'Z'] +let alpha = minuscule | majuscule +let alphanum = alpha | chiffre | '_' +let commentaire = + (* Commentaire bloc *) + ("/*" [^ '*']* '*'* ([^ '*' '/'] [^ '*']* '*'*)* '/') + (* Commentaire fin de ligne *) + | "//" [^'\n']* + +rule main = parse + | ['\n' '\t' ' ']+ { main lexbuf } + | commentaire { (main lexbuf) } + | "import" { IMPORT } + | "int" { INT } + | "float" { FLOAT } + | "boolean" { BOOL } + | "char" { CHAR } + | "void" { VOID } + | "String" { STRING } + | "{" { ACCOUV } + | "}" { ACCFER } + | "," { VIRG } + | ";" { PTVIRG } + | "(" { PAROUV } + | ")" { PARFER } + | "[" { CROOUV } + | "]" { CROFER } + | "if" { SI } + | "else" { SINON } + | "while" { TANTQUE } + | "return" { RETOUR } + | "=" { ASSIGN } + | "<" { OPINF } + | ">" { OPSUP } + | "<=" { OPINFEG } + | ">=" { OPSUPEG } + | "==" { OPEG } + | "!=" { OPNONEG } + | "+" { OPPLUS } + | "-" { OPMOINS } + | "||" { OPOU } + | "*" { OPMULT } + | "%" { OPMOD } + | "/" { OPDIV } + | "&&" { OPET } + | "!" { OPNON } + | "." { OPPT } + | chiffre+ as texte { (ENTIER (int_of_string texte)) } + | "0x" hexadecimal+ as texte { (ENTIER (int_of_string texte)) } + | "0o" octal+ as texte { (ENTIER (int_of_string texte)) } + | "0b" binaire+ as texte { (ENTIER (int_of_string texte)) } + | chiffre+"."chiffre+ as texte { (FLOTTANT (float_of_string texte))} + | ("true" | "false") as texte { (BOOLEEN (bool_of_string texte)) } + | '\'' _ '\'' as texte { (CARACTERE texte.[1]) } + | '\"' ([^ '\"' '\\'] | ('\\' _))* '\"' as texte { (CHAINE texte) } + | "null" { VIDE } + | "new" { NOUVEAU } + | ('_' | minuscule) alphanum* as texte { (IDENT texte) } + | majuscule alphanum* as texte { (TYPEIDENT texte) } + | eof { FIN } + | _ as texte { (print_string "Erreur lexicale : ");(print_char texte);(print_newline ()); VIDE } + +{ + +} diff --git a/TP2/mainJava.ml b/TP2/mainJava.ml new file mode 100755 index 0000000..1df3bcb --- /dev/null +++ b/TP2/mainJava.ml @@ -0,0 +1,71 @@ +open ParserJava + +(* Fonction d'affichage des unités lexicales et des données qu'elles contiennent *) +let printToken t = + (print_endline + (match t with + | IMPORT -> "import" + | IDENT (texte) -> texte + | TYPEIDENT (texte) -> texte + | INT -> "int" + | FLOAT -> "float" + | BOOL -> "bool" + | CHAR -> "char" + | VOID -> "void" + | STRING -> "String" + | ACCOUV -> "{" + | ACCFER -> "}" + | PTVIRG -> ";" + | VIRG -> "," + | PAROUV -> "(" + | PARFER -> ")" + | CROOUV -> "[" + | CROFER -> "]" + | SI -> "if" + | SINON -> "else" + | TANTQUE -> "while" + | RETOUR -> "return" + | ENTIER (texte) -> (string_of_int texte) + | FLOTTANT (texte) -> (string_of_float texte) + | BOOLEEN (texte) -> (string_of_bool texte) + | CARACTERE (texte) -> (String.make 1 texte) + | CHAINE (texte) -> texte + | VIDE -> "null" + | NOUVEAU -> "new" + | FIN -> "EOF" + | ASSIGN -> "=" + | OPINF -> "<" + | OPSUP -> ">" + | OPINFEG -> "<=" + | OPSUPEG -> ">=" + | OPEG -> "==" + | OPNONEG -> "!=" + | OPPLUS -> "+" + | OPMOINS -> "-" + | OPOU -> "||" + | OPMULT -> "*" + | OPMOD -> "%" + | OPDIV -> "/" + | OPET -> "&&" + | OPNON -> "!" + | OPPT -> "."));; + +(* Analyse lexicale du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + let token = ref (LexerJava.main lexbuf) in + while ((!token) != FIN) do + (printToken (!token)); + (token := (LexerJava.main lexbuf)) + done +else + (print_endline "MainMuJava fichier");; + +(* Analyse lexicale, syntaxique et sémantique du fichier passé en paramètre de la ligne de commande *) +if (Array.length Sys.argv > 1) +then + let lexbuf = (Lexing.from_channel (open_in Sys.argv.(1))) in + (ParserJava.fichier LexerJava.main lexbuf) +else + (print_endline "MainJava fichier");; diff --git a/TP2/parserJava.mly b/TP2/parserJava.mly new file mode 100755 index 0000000..2e3bb59 --- /dev/null +++ b/TP2/parserJava.mly @@ -0,0 +1,165 @@ +%{ + +(* Partie recopiee dans le fichier CaML genere. *) +(* Ouverture de modules exploites dans les actions *) +(* Declarations de types, de constantes, de fonctions, d'exceptions exploites dans les actions *) + +(* let nbrVariables = ref 0;; *) + +let nbrFonctions = ref 0;; + +%} + +/* Declaration des unites lexicales et de leur type si une valeur particuliere leur est associee */ + +%token IMPORT +%token IDENT TYPEIDENT +%token INT FLOAT BOOL CHAR VOID STRING +%token ACCOUV ACCFER PAROUV PARFER CROOUV CROFER +%token PTVIRG VIRG +%token SI SINON TANTQUE RETOUR +/* Defini le type des donnees associees a l'unite lexicale */ +%token ENTIER +%token FLOTTANT +%token BOOLEEN +%token CARACTERE +%token CHAINE +%token VIDE +%token NOUVEAU +%token ASSIGN +%token OPINF OPSUP OPINFEG OPSUPEG OPEG OPNONEG +%token OPPLUS OPMOINS OPOU +%token OPMULT OPMOD OPDIV OPET +%token OPNON +%token OPPT +/* Unite lexicale particuliere qui represente la fin du fichier */ +%token FIN + +/* Declarations des regles d'associative et de priorite pour les operateurs */ +/* La priorite est croissante de haut en bas */ +/* Associatif a droite */ +%right ASSIGN /* Priorite la plus faible */ +/* Non associatif */ +%nonassoc OPINF OPSUP OPINFEG OPSUPEG OPEG OPNONEG +/* Associatif a gauche */ +%left OPPLUS OPMOINS OPOU +%left OPMULT OPMOD OPDIV OPET +%right OPNON +%left OPPT PAROUV CROOUV /* Priorite la plus forte */ + +/* Type renvoye pour le nom terminal fichier */ +%type fichier +%type variables + +/* Le non terminal fichier est l'axiome */ +%start fichier + +%% /* Regles de productions */ + +fichier : programme FIN { (print_endline "fichier : programme FIN");(print_string "Nombre de fonctions : ");(print_int !nbrFonctions);(print_newline()) } + +programme : /* Lambda, mot vide */ { (nbrFonctions := 0); (print_endline "programme : /* Lambda, mot vide */") } + | fonction programme { (nbrFonctions := !nbrFonctions + 1);(print_endline "programme : fonction programme") } + +typeStruct : typeBase declTab { (print_endline "typeStruct : typeBase declTab") } + +typeBase : INT { (print_endline "typeBase : INT") } + | FLOAT { (print_endline "typeBase : FLOAT") } + | BOOL { (print_endline "typeBase : BOOL") } + | CHAR { (print_endline "typeBase : CHAR") } + | STRING { (print_endline "typeBase : STRING") } + | TYPEIDENT { (print_endline "typeBase : TYPEIDENT") } + +declTab : /* Lambda, mot vide */ { (print_endline "declTab : /* Lambda, mot vide */") } + | CROOUV CROFER { (print_endline "declTab : CROOUV CROFER") } + +fonction : entete bloc { (print_endline "fonction : entete bloc") } + +entete : typeStruct IDENT PAROUV parsFormels PARFER { (print_endline "entete : typeStruct IDENT PAROUV parsFormels PARFER") } + | VOID IDENT PAROUV parsFormels PARFER { (print_endline "entete : VOID IDENT PAROUV parsFormels PARFER") } + +parsFormels : /* Lambda, mot vide */ { (print_endline "parsFormels : /* Lambda, mot vide */") } + | typeStruct IDENT suiteParsFormels { (print_endline "parsFormels : typeStruct IDENT suiteParsFormels") } + +suiteParsFormels : /* Lambda, mot vide */ { (print_endline "suiteParsFormels : /* Lambda, mot vide */") } + | VIRG typeStruct IDENT suiteParsFormels { (print_endline "suiteParsFormels : VIRG typeStruct IDENT suiteParsFormels") } + +bloc : ACCOUV /* $1 */ variables /* $2 */ instructions /* $3 */ ACCFER /* $4 */ + { + (print_endline "bloc : ACCOUV variables instructions ACCFER"); + (print_string "Nombre de variables = "); + (print_int $2); + (print_newline ()); + (print_string "Nombre d'instructions = "); + (print_int $3); + (print_newline ()) + } + +variables : /* Lambda, mot vide */ {(print_endline "variables : /* Lambda, mot vide */");0} + | variable /* $1 */ variables /* $2 */ {(print_endline "variables : variable variables");($2 + 1)} + +variable : typeStruct IDENT PTVIRG { (print_endline "variable : typeStruct IDENT PTVIRG") } + +instructions : /* Lambda, mot vide */ { (print_endline "instructions : /* Lambda, mot vide */");0} + | instruction /* $1 */ instructions /* $2 */ { (print_endline "instructions : instruction instructions");($2 + 1) } + +/* A FAIRE : Completer pour ajouter les autres formes d'instructions */ +instruction : expression PTVIRG { (print_endline "instruction : expression PTVIRG") } + | TANTQUE PAROUV expression PARFER bloc { (print_endline "instruction : TANTQUE PAROUV expression PARFER bloc") } + | RETOUR expression PTVIRG { (print_endline "instruction : RETURN expression PTVIRG") } + | SI PAROUV expression PARFER bloc else_option {(print_endline "instruction : SI PAROUV expression PARFER bloc else_option")} + +expression : unaires sub_expression_1 {(print_endline "expression : unaires sub_expressions_1")} + | expression binaire expression {(print_endline "expression : expression binaire expression")} + +else_option : /* Lambda, mot vide */ {(print_endline "else_option : /* Lambda, mot vide */")} + | SINON bloc {(print_endline "else_option : SINON bloc")} + +sub_expression_1 : ENTIER {(print_endline "expression : ENTIER")} + | FLOTTANT {(print_endline "expression : FLOTTANT")} + | BOOLEEN {(print_endline "expression : BOOLEEN")} + | CARACTERE {(print_endline "expression : CARACTERE")} + | VIDE {(print_endline "expression : VIDE")} + | NOUVEAU IDENT sub_expression_2 {(print_endline "expression : NOUVEAU IDENT")} + | IDENT suffixes {(print_endline "expression : IDENT suffixes")} + | PAROUV expression PARFER suffixes {(print_endline "expression : PAROUV expression PARFER suffixes")} + | OPPLUS expression %prec OPNON {} + +sub_expression_2 : PAROUV PARFER {(print_endline "sub_expression_2 : ( )" )} + | CROOUV expression CROFER {(print_endline "sub_expression_2 : [ expression ]" )} + +binaire : ASSIGN {(print_endline "binaire : =")} + | OPINF {(print_endline "binaire : <")} + | OPSUP {(print_endline "binaire : >")} + | OPINFEG {(print_endline "binaire : <=")} + | OPSUPEG {(print_endline "binaire : >=")} + | OPEG {(print_endline "binaire : ==")} + | OPNONEG {(print_endline "binaire : !=")} + | OPPLUS {(print_endline "binaire : +")} + | OPMOINS {(print_endline "binaire : -")} + | OPOU {(print_endline "binaire : ||")} + | OPMULT {(print_endline "binaire : *")} + | OPMOD {(print_endline "binaire : %")} + | OPDIV {(print_endline "binaire : /")} + | OPET {(print_endline "binaire : &&")} + | OPPT {(print_endline "binaire : .")} + +unaires : /* Lambda, mot vide */ {(print_endline "unaires : /* Lambda, mot vide */")} + | unaire unaires {(print_endline "unaires : unaire unaires")} + +unaire : PAROUV typeStruct PARFER {(print_endline "unaire : ( typeStruct )")} + | OPPLUS {(print_endline "unaire : +")} + | OPMOINS {(print_endline "unaire : -")} + | OPNON {(print_endline "unaire : !")} + +suffixes : /* Lambda, mot vide */ {(print_endline "suffixe : /* Lambda, mot vide */")} + | suffixe suffixes {(print_endline "suffixes : suffixe suffixes")} + +suffixe : CROOUV expression CROFER {(print_endline "suffixe : CROOUV expression CROFER")} + | PAROUV sub_suffixe PARFER {(print_endline "suffixe : PAROUV sub_suffixe PARFER")} + +sub_suffixe : /* Lambda, mot vide */ {(print_endline "sub_suffixe : /* Lambda, mot vide */")} + | expression {(print_endline "sub_suffixe : expression")} + | sub_suffixe VIRG sub_suffixe {(print_endline "expression : sub_suffixe binaire sub_suffixe")} + +%% diff --git a/TP2/tests/exemple-complique.java b/TP2/tests/exemple-complique.java new file mode 100755 index 0000000..37455d5 --- /dev/null +++ b/TP2/tests/exemple-complique.java @@ -0,0 +1,49 @@ + +/* Cet exemple respecte la syntaxe (grammaire) de microjava, avec des + * commentaires, des chaînes complexes, des réels bizarres... + * Les constructions qui ne sont pas trait + * Ce programme est sémantiquement faux (typage en particulier) + */ + +/* class Point { + private int x; + private int y; + + private String toto; + + // rien { + public int get_x () */ +{ return x; } +// public void set_x (int _x) +{ x = _x; } + +// private void essai_string () + { + toto = "machin avec des espaces et des \" quotes +et multiligne avec echappement \n meme a la fin \\"; foo(); "et une autre chaine"; + x = 3.14 + .14 + 3. + 14e-1 + .3e1; + y = 'a' + '\13' + 0x2A; + } +} + +/* ghjd /* ****/ +/* class PointColore extends Point { + public int c; + public int get_c () */ + { return c*2; } +/* } */ +/***** +class PointColore extends Point **g + // dfgkhdk *f ** */ + +/* public class Exemple { + public static void main (String[] argv) */ + { + int x; + bool b; + b = true; + if (b) { + x = 2*x + 3; + } + } +// } diff --git a/TP2/tests/exemple-simple.java b/TP2/tests/exemple-simple.java new file mode 100755 index 0000000..e12c37a --- /dev/null +++ b/TP2/tests/exemple-simple.java @@ -0,0 +1,32 @@ + +// Note: ce fichier ne respecte pas la *grammaire* de micro-java +// Il ne fait qu'enumerer les tokens de la grammaire. + +// mot clefs +// class extends private public static main + +// types +int void float bool char String + +// structures de controle +if else while return + +// instructions +new null + +// operateurs +< > >= <= == != ++ - / * % && || ! = . + +// parentheses +( [ { } ] ) + +// separateurs +, ; + +// constantes +true false 0 245 1_234_567 0b1101 0B1_0100_1100 077 01_345 0xFF 0X1_FF00_1234 'a' 567.34 1e-5 .12 +"bonjour" + +// noms +x toto Point diff --git a/TP2/tests/exemple-tres-simple.java b/TP2/tests/exemple-tres-simple.java new file mode 100755 index 0000000..b434f6d --- /dev/null +++ b/TP2/tests/exemple-tres-simple.java @@ -0,0 +1,3 @@ +, /* test */ int while // ceci est un autre test +" te \" st " +123 diff --git a/TP2/tests/exemple.java b/TP2/tests/exemple.java new file mode 100755 index 0000000..ace6482 --- /dev/null +++ b/TP2/tests/exemple.java @@ -0,0 +1,2 @@ +453 while 45, 4, 8 +int 4 int while , 8 diff --git a/TP2/tests/test.java b/TP2/tests/test.java new file mode 100755 index 0000000..3005904 --- /dev/null +++ b/TP2/tests/test.java @@ -0,0 +1,3 @@ +// +index + 000123 + diff --git a/TP2/tests/test00.java b/TP2/tests/test00.java new file mode 100755 index 0000000..5da92e8 --- /dev/null +++ b/TP2/tests/test00.java @@ -0,0 +1,30 @@ +void f() { + int i; + int j; + return 1.0 = 2 + 3 - 4 * 5 / 6 % 7 || 8 && 9 == 10 != 11 < 12 > 13 <= 14 >= 15; + + -3.14; + null; + new bonjour(); + new entiers[10]; + + test(a, b, c, d); + tableau[13]; + + while (1) { + 2; + } + + if (10 == 3) { + int k; + } + else { + while (1) { + 2; + } + } +} + +void deuxieme() { + int k; +} diff --git a/TP3/A_FAIRE.txt b/TP3/A_FAIRE.txt new file mode 100755 index 0000000..6531e06 --- /dev/null +++ b/TP3/A_FAIRE.txt @@ -0,0 +1,145 @@ +TP Outils Mathématiques Informatique : Analyse Syntaxique par Descente Récursive +================================================================================ + +Le but de ce TP est d'apprendre à écrire un analyseur syntaxique +descendant récursif et à le tester. + +Nous allons dans une première étape traiter le cas de la grammaire manipulée +en TD, puis nous étendrons celle-ci : + +A/ La syntaxe du langage est un sous ensemble des expressions en CaML : + +E est l'axiome. + + E -> ER = E + E -> ER + ER -> ER + T + ER -> ER - T + ER -> T + T -> T * F + T -> T / F + T -> F + F -> - F + F -> ( E ) + F -> ident + F -> true + F -> false + F -> number + +Voici une grammaire LL(1) possible (vous pouvez aussi partir de celle proposée +en TD pour les expressions de bloc) : + + E -> ER EX - ( ident true false number + EX -> = ER EX = + EX -> ) $ + ER -> T TX - ( ident true false number + TX -> + T TX + + TX -> - T TX - + TX -> = ) $ + T -> F FX - ( ident true false number + FX -> * F FX * + FX -> / F FX / + FX -> + - = ) $ + F -> - F - + F -> ( E ) ( + F -> ident ident + F -> true true + F -> false false + F -> number number + +1) Écrire quelques programmes de test respectant la syntaxe de miniml. + +2) L'analyseur lexical étant fourni (généré par camllex à partir du + fichier Scanner.mll), écrire un analyseur descendant récursif pour + miniml dans le fichier Syntax.ml, suivant le principe étudié en TD. + + La compilation est effectuée par la commande : dune build Main.exe + +3) Tester cet analyseur syntaxique. + +================================================================ +B/ Simplification de l'analyseur par notation monadique + +L'analyseur développé dans l'exercice précédent est relativement complexe à +cause de la gestion des succès/échec et de la transmission de la liste des +terminaux en cours d'analyse. + +Il est possible de simplifier la programmation en utilisant une notation +monadique pour factoriser ce traitement répétitif. + +Celle-ci est composée de trois parties : + - le type de donnée monadique : parseResult + - la fonction : inject qui construit ce type à partir d'une liste de terminaux + - la fonction : bind (opérateur >>=) qui combine les fonctions d'analyse. + +1) Étudier le fichier SyntaxMonad.ml qui implante le même analyseur + que l'exercice A/ en utilisant cette notation. + + La compilation est effectuée par la commande : dune build MainMonad.exe + +================================================================ +C/ La syntaxe du langage étendue sera celle d'un mini CaML. + +E0 est l'axiome. + +Nous avons mis en évidence les nouvelles règles et les règles modifiées. + +* E0 -> function ident -> E0 +* E0 -> let ident = E0 in E0 +* E0 -> letrec ident = E0 in E0 +* E0 -> if E0 then E0 else E0 +* E0 -> E + E -> ER = E + E -> ER + ER -> ER + T + ER -> ER - T + ER -> T + T -> T * F + T -> T / F + T -> F + F -> - F +* F -> ( E0 ) +* F -> ( E0 ) (E0) + F -> ident +* F -> ident (E0) + F -> true + F -> false + F -> number + +1) Écrire quelques programmes de test respectant la syntaxe de miniml. + +2) Cette grammaire n'est pas LL(1), factoriser celle-ci et éliminer la + récursivité à gauche. + +LL(1) + E0 -> function ident -> E0 + E0 -> let ident = E0 in E0 + E0 -> letrec ident = E0 in E0 + E0 -> if E0 then E0 else E0 + E0 -> E + E -> ER = E + E -> ER + ER -> T EY + EY -> + T EY + EY -> - T EY + EY -> + T -> F TY + TY -> * F TY + TY -> / F TY + TY -> + F -> - F + F -> ( E0 ) + F -> ( E0 ) (E0) + F -> ident + F -> ident (E0) + F -> true + F -> false + F -> number + +3) L'analyseur lexical étant fourni (généré par camllex à partir du + fichier Scanner.mll), écrire un analyseur descendant récursif pour + miniML en exploitant la technique monadique présentée dans + l'exercice précédent, vous modifierez pour cela le fichier + SyntaxMonad.ml. + +4) Tester cet analyseur syntaxique. diff --git a/TP3/Lex.ml b/TP3/Lex.ml new file mode 100755 index 0000000..0a0073e --- /dev/null +++ b/TP3/Lex.ml @@ -0,0 +1,88 @@ +(* open List *) + +type token = + | EOSToken + | FunctionToken + | BodyToken + | IfToken + | ThenToken + | ElseToken + | LetToken + | InToken + | TrueToken + | FalseToken + | RecToken + | IdentToken of string + | NumberToken of int + | EqualToken + | DifferentToken + | LesserToken + | GreaterToken + | LesserEqualToken + | GreaterEqualToken + | PlusToken + | MinusToken + | TimesToken + | DivideToken + | LeftParenthesisToken + | RightParenthesisToken +;; + +type inputStream = token list;; + +(* string_of_token : token -> string *) +(* Converti un token en une chaîne de caractère*) +let string_of_token token = + match token with + | EOSToken -> "$" + | FunctionToken -> "function" + | BodyToken -> "->" + | IfToken -> "if" + | ThenToken -> "then" + | ElseToken -> "else" + | LetToken -> "let" + | InToken -> "in" + | TrueToken -> "true" + | FalseToken -> "false" + | RecToken -> "letrec" + | NumberToken xxx -> string_of_int xxx + | IdentToken name -> name + | EqualToken -> "=" + | DifferentToken -> "!=" + | LesserToken -> "<" + | GreaterToken -> ">" + | LesserEqualToken -> "<=" + | GreaterEqualToken -> ">=" + | PlusToken -> "+" + | MinusToken -> "-" + | TimesToken -> "*" + | DivideToken -> "/" + | LeftParenthesisToken -> "(" + | RightParenthesisToken -> ")" +;; + +(* string_of_stream : inputStream -> string *) +(* Converti un inputStream (liste de token) en une chaîne de caractère *) +let string_of_stream stream = + List.fold_right (fun t tq -> (string_of_token t) ^ " " ^ tq ) stream "";; + + +(* peekAtFirstToken : inputStream -> token *) +(* Renvoie le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let peekAtFirstToken stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible d'acceder au premier element d'un inputStream vide" + |t::_ -> t;; + +(* advanceInStream : inputStream -> inputStream *) +(* Consomme le premier élément d'un inputStream *) +(* Erreur : si l'inputStream est vide *) +let advanceInStream stream = + match stream with + (* Normalement, ne doit jamais se produire sauf si la grammaire essaie de lire *) + (* après la fin de l'inputStream. *) + | [] -> failwith "Impossible de consommer le premier element d'un inputStream vide" + | _::q -> q;; diff --git a/TP3/Main.ml b/TP3/Main.ml new file mode 100755 index 0000000..ff41516 --- /dev/null +++ b/TP3/Main.ml @@ -0,0 +1,22 @@ +open Lex +open Scanner +open Syntax + +(* main : unit -> unit *) +(* Analyse le contenu d'un fichier passé en paramètre ou l'entrée standard si aucun fichier n'est donné *) +(* Affiche OK si l'analyse syntaxique c'est bien passée et KO sinon *) +let main () = + let cin = + if Array.length Sys.argv > 1 then + open_in Sys.argv.(1) + else + stdin + in + let lexbuf = Lexing.from_channel cin in + match (parseE (scanner lexbuf)) + with + | Success [EOSToken] -> print_endline "Ok" + | _ -> print_endline "Ko" +;; + +main();; diff --git a/TP3/MainMonad.ml b/TP3/MainMonad.ml new file mode 100755 index 0000000..1a93ee5 --- /dev/null +++ b/TP3/MainMonad.ml @@ -0,0 +1,22 @@ +open Lex +open Scanner +open SyntaxMonad + +(* main : unit -> unit *) +(* Analyse le contenu d'un fichier passé en paramètre ou l'entrée standard si aucun fichier n'est donné *) +(* Affiche OK si l'analyse syntaxique c'est bien passée et KO sinon *) +let main () = + let cin = + if Array.length Sys.argv > 1 then + open_in Sys.argv.(1) + else + stdin + in + let lexbuf = Lexing.from_channel cin in + match (parseE (scanner lexbuf)) + with + | Success [EOSToken] -> print_endline "Ok" + | _ -> print_endline "Ko" +;; + +main();; diff --git a/TP3/Scanner.mll b/TP3/Scanner.mll new file mode 100755 index 0000000..60ca7fa --- /dev/null +++ b/TP3/Scanner.mll @@ -0,0 +1,118 @@ +{ + open Lex + open Printf +} + +let digit = ['0'-'9'] +let id = ['a'-'z'] ['a'-'z' '0'-'9']* + +rule scanner = parse + | [' ' '\t' '\n' '\r'] { (scanner lexbuf) } (* eat up whitespace *) + | '(' + { + LeftParenthesisToken :: (scanner lexbuf) + } + | ')' + { + RightParenthesisToken :: (scanner lexbuf) + } + | '=' + { + EqualToken :: (scanner lexbuf) + } + | "!=" + { + DifferentToken :: (scanner lexbuf) + } + | '=' + { + EqualToken :: (scanner lexbuf) + } + | '<' + { + LesserToken :: (scanner lexbuf) + } + | '>' + { + GreaterToken :: (scanner lexbuf) + } + | "<=" + { + LesserEqualToken :: (scanner lexbuf) + } + | ">=" + { + GreaterEqualToken :: (scanner lexbuf) + } + | '+' + { + PlusToken :: (scanner lexbuf) + } + | '-' + { + MinusToken :: (scanner lexbuf) + } + | '*' + { + TimesToken :: (scanner lexbuf) + } + | '/' + { + DivideToken :: (scanner lexbuf) + } + | "->" + { + BodyToken :: (scanner lexbuf) + } + | "function" + { + FunctionToken :: (scanner lexbuf) + } + | "if" + { + IfToken :: (scanner lexbuf) + } + | "then" + { + ThenToken :: (scanner lexbuf) + } + | "else" + { + ElseToken :: (scanner lexbuf) + } + | "let" + { + LetToken :: (scanner lexbuf) + } + | "in" + { + InToken :: (scanner lexbuf) + } + | "letrec" + { + RecToken :: (scanner lexbuf) + } + | "true" + { + TrueToken :: (scanner lexbuf) + } + | "false" + { + FalseToken :: (scanner lexbuf) + } + | digit+ as inum + { + (NumberToken (int_of_string inum)) :: (scanner lexbuf) + } + | id as text + { + (IdentToken ("\"" ^ text ^"\"")) :: (scanner lexbuf) + } + | _ as c + { printf "Unrecognized character: %c\n" c; + (scanner lexbuf) + } + | eof {[ EOSToken ] } + +{ +} diff --git a/TP3/Syntax.ml b/TP3/Syntax.ml new file mode 100755 index 0000000..38f3bf4 --- /dev/null +++ b/TP3/Syntax.ml @@ -0,0 +1,209 @@ +open Lex + +type parseResult = + | Success of inputStream + | Failure +;; + +(* + E -> ER = E + E -> ER + ER -> ER + T + ER -> ER - T + ER -> T + T -> T * F + T -> T / F + T -> F + F -> - F + F -> ( E ) + F -> ident + F -> true + F -> false + F -> number +*) + +(* + LL(1) Règle de production / Symboles directeurs + #1 - E -> function ident fleche E { function } + #2 - E -> if E then E else E { if } + #5 - E -> ER EX | { -, number, ident, true, false, ( } + #6 - EX -> = ER EX | { = } + #7 - EX -> | { $, ), then, else } + #8 - ER -> T TX | { -, number, ident, true, false, ( } + #9 - TX -> + T TX | { + } + #10 - TX -> - T TX | { - } + #11 - TX -> | { $, =, ), then, else } + #12 - T -> F FX | { -, number, ident, true, false, ( } + #13 - FX -> * F FX | { * } + #14 - FX -> / F FX | { / } + #15 - FX -> | { $, +, -, =, ), then, else } + #16 - F -> - F | { - } + #17 - F -> number | { number } + #20 - F -> ident | { ident } + #21 - F -> true | { true } + #22 - F -> false | { false } + #23 - F -> ( E ) | { ( } +*) + +(* accept : token -> inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien le token attendu *) +(* et avance dans l'analyse si c'est le cas *) +let accept expected stream = + match (peekAtFirstToken stream) with + | token when (token = expected) -> + (print_endline (string_of_token token)); + (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptIdent : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un identifiant *) +(* et avance dans l'analyse si c'est le cas *) +let acceptIdent stream = + match (peekAtFirstToken stream) with + | (IdentToken nom) -> + (print_endline nom); + (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptNumber : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un nombre *) +(* et avance dans l'analyse si c'est le cas *) +let acceptNumber stream = + match (peekAtFirstToken stream) with + | (NumberToken _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* parseE : inputStream -> parseResult *) +(* Analyse du non terminal E *) +let rec parseE stream = + (* + (print_endline (string_of_stream stream)); + *) + (print_endline "E"); + (match (peekAtFirstToken stream) with + (* regle #5 - E -> ER EX | { -, number, ident, true, false, ( } *) + (* Symboles directeurs *) + | (IdentToken _) | (NumberToken _) | TrueToken | FalseToken | + MinusToken | LeftParenthesisToken -> + (* Regle *) + (* Analyse ER *) + (match (parseER stream) with + | (Success next) -> + (* En cas de succes, analyse EX *) + parseEX next + | _ -> Failure) + | _ -> Failure) + +(* parseEX : inputStream -> parseResult *) +(* Analyse du non terminal EX *) +and parseEX stream = + (print_endline "EX"); + (match (peekAtFirstToken stream) with + (* regle #6 - EX -> = ER EX | { = } *) + | EqualToken -> (match (accept EqualToken stream) with + | Success next -> (match (parseER next) with + | Success next2 -> (parseEX next2) + | _ -> Failure) + | _ -> Failure) + (* regle #7 - EX -> | { $, ) } *) + | EOSToken | RightParenthesisToken | ThenToken | ElseToken -> (Success stream) + | _ -> Failure) + +(* parseER : inputStream -> parseResult *) +(* Analyse du non terminal ER *) +and parseER stream = + (print_endline "ER"); + (match (peekAtFirstToken stream) with + (* regle #8 - ER -> T TX | { -, number, ident, true, false, ( } *) + | (IdentToken _) | (NumberToken _) | TrueToken | FalseToken | MinusToken | LeftParenthesisToken -> + (match (parseT stream) with + | Success next -> (parseTX next) + | _ -> Failure) + | _ -> Failure) + +(* parseTX : inputStream -> parseResult *) +(* Analyse du non terminal TX *) +and parseTX stream = + (print_endline "TX"); + (match (peekAtFirstToken stream) with + (* regle #9 - TX -> + T TX | { + } *) + | PlusToken -> (match (accept PlusToken stream) with + | Success next -> ( + match (parseT next) with + | Success next -> (parseTX next) + | _ -> Failure) + | _ -> Failure) + (* regle #10 - TX -> - T TX | { - } *) + | MinusToken -> (match (accept MinusToken stream) with + | Success next -> ( + match (parseT next) with + | Success next -> (parseTX next) + | _ -> Failure) + | _ -> Failure) + (* regle #11 - TX -> | { $, =, ) } *) + | EOSToken | EqualToken | RightParenthesisToken -> Success stream + | _ -> Failure) + +(* parseT : inputStream -> parseResult *) +(* Analyse du non terminal T *) +and parseT stream = + (print_endline "T"); + (match (peekAtFirstToken stream) with + (* regle #12 - T -> F FX | { -, number, ident, true, false, ( } *) + | (IdentToken _) | (NumberToken _) | TrueToken | FalseToken | + MinusToken | LeftParenthesisToken -> (match (parseF stream) with + | Success next -> (parseFX next) + | _ -> Failure) + | _ -> Failure) + +(* parseFX : inputStream -> parseResult *) +(* Analyse du non terminal FX *) +and parseFX stream = + (print_endline "FX"); + (match (peekAtFirstToken stream) with + (* regle #13 - FX -> * F FX | { * } *) + | TimesToken -> (match (accept TimesToken stream) with + | Success next -> ( + match (parseF next) with + | Success next -> (parseFX next) + | _ -> Failure) + | _ -> Failure) + (* regle #14 - FX -> / F FX | { / } *) + | DivideToken -> (match (accept DivideToken stream) with + | Success next -> ( + match (parseF next) with + | Success next -> (parseFX next) + | _ -> Failure) + | _ -> Failure) + (* regle #15 - FX -> | { $, +, -, =, ) } *) + | EOSToken | PlusToken | MinusToken | EqualToken | RightParenthesisToken -> (Success stream) + | _ -> Failure) + +(* parseF : inputStream -> parseResult *) +(* Analyse du non terminal F *) +and parseF stream = + (print_endline "F"); + (match (peekAtFirstToken stream) with + (* regle #16 - F -> - F | { - } *) + | MinusToken -> (match (accept MinusToken stream) with + | Success next -> (parseF next) + | _ -> Failure) + (* regle #17 - F -> number | { number } *) + | NumberToken _ -> (acceptNumber stream) + (* regle #20 - F -> ident | { ident } *) + | IdentToken _ -> (acceptIdent stream) + (* regle #21 - F -> true | { true } *) + | TrueToken -> (accept TrueToken stream) + (* regle #22 - F -> false | { false } *) + | FalseToken -> (accept FalseToken stream) + (* regle #23 - F -> ( E ) | { ( } *) + | LeftParenthesisToken -> (match (accept LeftParenthesisToken stream) with + | Success next -> (match (parseE next) with + | Success next2 -> (accept RightParenthesisToken next2) + | _ -> Failure) + | _ -> Failure) + | _ -> Failure) +;; diff --git a/TP3/SyntaxMonad.ml b/TP3/SyntaxMonad.ml new file mode 100755 index 0000000..7d7b223 --- /dev/null +++ b/TP3/SyntaxMonad.ml @@ -0,0 +1,288 @@ +open Lex + +type parseResult = + | Success of inputStream + | Failure +;; + +(* + LL(1) + #01 - E0 -> function ident -> E0 + #02 - E0 -> let ident = E0 in E0 + #03 - E0 -> letrec ident = E0 in E0 + #04 - E0 -> if E0 then E0 else E0 + #05 - E0 -> F TY EY EX + #06 - EX -> = F TY EY EX + #07 - EX -> + #08 - EY -> + F TY EY + #09 - EY -> - F TY EY + #10 - EY -> + #11 - TY -> * F TY + #12 - TY -> / F TY + #13 - TY -> + #14 - F -> - F + #15 - F -> ( E0 ) FX + #16 - F -> ident FX + #17 - F -> true + #18 - F -> false + #19 - F -> number + #20 - FX -> ( E0 ) + #21 - FX -> +*) + +(* accept : token -> inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien le token attendu *) +(* et avance dans l'analyse si c'est le cas *) +let accept expected stream = + match (peekAtFirstToken stream) with + | token when (token = expected) -> + (print_endline (string_of_token token)); (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptIdent : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un identifiant *) +(* et avance dans l'analyse si c'est le cas *) +let acceptIdent stream = + match (peekAtFirstToken stream) with + | (IdentToken _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* acceptNumber : inputStream -> parseResult *) +(* Vérifie que le premier token du flux d'entrée est bien un nombre *) +(* et avance dans l'analyse si c'est le cas *) +let acceptNumber stream = + match (peekAtFirstToken stream) with + | (NumberToken _) -> (Success (advanceInStream stream)) + | _ -> Failure +;; + +(* Définition de la monade qui est composée de : *) +(* - le type de donnée monadique : parseResult *) +(* - la fonction : inject qui construit ce type à partir d'une liste de terminaux *) +(* - la fonction : bind (opérateur >>=) qui combine les fonctions d'analyse. *) + +(* inject inputStream -> parseResult *) +(* Construit le type de la monade à partir d'une liste de terminaux *) +let inject s = Success s;; + +(* bind : 'a m -> ('a -> 'b m) -> 'b m *) +(* bind (opérateur >>=) qui combine les fonctions d'analyse. *) +(* ici on utilise une version spécialisée de bind : + 'b -> inputStream + 'a -> inputStream + m -> parseResult +*) +(* >>= : parseResult -> (inputStream -> parseResult) -> parseResult *) +let (>>=) result f = + match result with + | Success next -> f next + | Failure -> Failure +;; + + +(* parseE0 : inputStream -> parseResult *) +(* Analyse du non terminal E0 *) +let rec parseE0 stream = + (* + (print_endline (string_of_stream stream)); + *) + (print_endline "E0"); + (match (peekAtFirstToken stream) with + (* regle #1 *) + | FunctionToken -> + inject stream >>= + accept FunctionToken >>= + acceptIdent >>= + accept BodyToken >>= + parseE0 + (* regle #2 *) + | LetToken -> + inject stream >>= + accept LetToken >>= + acceptIdent >>= + accept EqualToken >>= + parseE0 >>= + accept InToken >>= + parseE0 + (* regle #3 *) + | RecToken -> + inject stream >>= + accept RecToken >>= + acceptIdent >>= + accept EqualToken >>= + parseE0 >>= + accept InToken >>= + parseE0 + (* regle #4 if E then E else E *) + | IfToken -> + inject stream >>= + accept IfToken >>= + parseE0 >>= + accept ThenToken >>= + parseE0 >>= + accept ElseToken >>= + parseE0 + (* regle #5 *) + | ((IdentToken _) | (NumberToken _) | TrueToken | FalseToken | MinusToken | LeftParenthesisToken ) -> + inject stream >>= + parseF >>= + parseTY >>= + parseEY >>= + parseEX + | _ -> Failure) + +(* parseEX : inputStream -> parseResult *) +(* Analyse du non terminal EX *) +and parseE stream = + (print_endline "EX"); + (match (peekAtFirstToken stream) with + (* regle #6 *) + | EqualToken -> + inject stream >>= + accept EqualToken >>= + parseF >>= + parseTY >>= + parseEY >>= + parseEX + (* regle #7 *) + | (RightParenthesisToken | ElseToken | ThenToken | InToken) -> + inject stream + | EOSToken -> + inject stream + | _ -> Failure) + +(* parseER : inputStream -> parseResult *) +(* Analyse du non terminal ER *) +and parseER stream = + (print_endline "ER"); + (match (peekAtFirstToken stream) with + (* regle #8 *) + | ((IdentToken _) | (NumberToken _) | TrueToken | FalseToken | MinusToken | LeftParenthesisToken) -> + inject stream >>= + parseT >>= + parseTX + | _ -> Failure) + +(* parseTX : inputStream -> parseResult *) +(* Analyse du non terminal TX *) +and parseTX stream = + (print_endline "TX"); + (match (peekAtFirstToken stream) with + (* regle 9 *) + | PlusToken -> + inject stream >>= + accept PlusToken >>= + parseT >>= + parseTX + (* regle 10 *) + | MinusToken -> + inject stream >>= + accept MinusToken >>= + parseT >>= + parseTX + (* regle 11 *) + | (RightParenthesisToken | EqualToken | ElseToken | ThenToken | InToken) -> inject stream + | EOSToken -> inject stream + | _ -> Failure) + +(* parseT : inputStream -> parseResult *) +(* Analyse du non terminal T *) +and parseT stream = + (print_endline "T"); + (match (peekAtFirstToken stream) with + (* regle 12 *) + | ((IdentToken _) | (NumberToken _) | TrueToken | FalseToken | MinusToken | LeftParenthesisToken) -> + inject stream >>= + parseF >>= + parseFX + | _ -> Failure) + +(* parseFX : inputStream -> parseResult *) +(* Analyse du non terminal FX *) +and parseFX stream = + (print_endline "FX"); + (match (peekAtFirstToken stream) with + (* regle 13 *) + | TimesToken -> + inject stream >>= + accept TimesToken >>= + parseF >>= + parseFX + (* regle 14 *) + | DivideToken -> + inject stream >>= + accept DivideToken >>= + parseF >>= + parseFX + (* regle 15 *) + | (RightParenthesisToken | EqualToken | PlusToken | MinusToken | ElseToken | ThenToken | InToken) -> + inject stream + | EOSToken -> inject stream + | _ -> Failure) + +(* parseF : inputStream -> parseResult *) +(* Analyse du non terminal F *) +and parseF stream = + (print_endline "F"); + (match (peekAtFirstToken stream) with + (* regle 16 *) + | MinusToken -> + inject stream >>= + accept MinusToken >>= + parseF + (* regle 17 *) + | (NumberToken _) -> + inject stream >>= + acceptNumber + (* regle 20 *) + | ((IdentToken _) | LeftParenthesisToken) -> + inject stream >>= + parseFF >>= + parseARG + (* regle 21 *) + | TrueToken -> + inject stream >>= + accept TrueToken + (* regle 22 *) + | FalseToken -> + inject stream >>= + accept FalseToken + | _ -> Failure) + +(* parseFF : inputStream -> parseResult *) +(* Analyse du non terminal FF *) +and parseFF stream = + (print_endline "FF"); + (match (peekAtFirstToken stream) with + (* regle 23 ( E ) *) + | LeftParenthesisToken -> + inject stream >>= + accept LeftParenthesisToken >>= + parseE >>= + accept RightParenthesisToken + (* regle 24 *) + | IdentToken _ -> + inject stream >>= + acceptIdent + | _ -> Failure) + +(* parseARG : inputStream -> parseResult *) +(* Analyse du non terminal ARG *) +and parseARG stream = + (print_endline "ARG"); + (match (peekAtFirstToken stream) with + (* regle 25 - ARG -> ( E ) *) + | LeftParenthesisToken -> + inject stream >>= + accept LeftParenthesisToken >>= + parseE >>= + accept RightParenthesisToken + (* regle 26 - ARG -> *) + | (RightParenthesisToken | EqualToken | PlusToken | MinusToken | ElseToken | ThenToken | InToken | TimesToken | DivideToken ) -> + inject stream + | EOSToken -> + inject stream + | _ -> Failure) +;; diff --git a/TP3/dune b/TP3/dune new file mode 100755 index 0000000..7ac8d40 --- /dev/null +++ b/TP3/dune @@ -0,0 +1,4 @@ +(ocamllex Scanner) + +(executables + (names Main MainMonad)) diff --git a/TP3/dune-project b/TP3/dune-project new file mode 100755 index 0000000..0636ab6 --- /dev/null +++ b/TP3/dune-project @@ -0,0 +1 @@ +(lang dune 1.11) diff --git a/TP3/tests/test.ml b/TP3/tests/test.ml new file mode 100755 index 0000000..5ce2119 --- /dev/null +++ b/TP3/tests/test.ml @@ -0,0 +1,27 @@ + +(* + LL(1) + #01 - E0 -> function ident -> E0 + #02 - E0 -> let ident = E0 in E0 + #03 - E0 -> letrec ident = E0 in E0 + #04 - E0 -> if E0 then E0 else E0 + #05 - E0 -> F TY EY EX + #06 - EX -> = F TY EY EX + #07 - EX -> + #08 - EY -> + F TY EY + #09 - EY -> - F TY EY + #10 - EY -> + #11 - TY -> * F TY + #12 - TY -> / F TY + #13 - TY -> + #14 - F -> - F + #15 - F -> ( E0 ) FX + #16 - F -> ident FI + #17 - F -> true + #18 - F -> false + #19 - F -> number + #20 - FX -> ( E0 ) + #21 - FX -> + #22 - FI -> ( EO ) + #23 - FI -> +*)