maj
This commit is contained in:
1
DEV3.4/ControleMachine/test/.bashrc
Normal file
1
DEV3.4/ControleMachine/test/.bashrc
Normal file
@@ -0,0 +1 @@
|
||||
export CLASSPATH=".:/usr/share/java/junit.jar:/usr/share/java/hamcrest-core.jar"
|
20
DEV3.4/ControleMachine/test/AbstractToken.java
Normal file
20
DEV3.4/ControleMachine/test/AbstractToken.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Classe Abstraite pour modéliser les éléments d'un programme après analyse lexicale (ou tokenization en franglais).
|
||||
*
|
||||
* Le programme est une succession de lexèmes ou jetons après analyse lexicale. Par exemple, un jeton contenant le nom d'une variable,
|
||||
* un jeton pour un symbole d'une opération etc.
|
||||
*
|
||||
* Une classe concrète étendant cette classe permet de modéliser un type de jeton, et d'adapter le traitement selon le type du jeton
|
||||
* lors de l'analyse syntaxique / compilation.
|
||||
*
|
||||
* On utilise simplement toString pour retrouver le texte initial.
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*/
|
||||
|
||||
|
||||
public abstract class AbstractToken {
|
||||
|
||||
|
||||
}
|
||||
|
23
DEV3.4/ControleMachine/test/Exemple.java
Normal file
23
DEV3.4/ControleMachine/test/Exemple.java
Normal file
@@ -0,0 +1,23 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class Exemple{
|
||||
public static void main(String[] args){
|
||||
// 3 + 4 × (2 − 1)
|
||||
// pas de parenthèse encore, je fais 3 + 4 * 2
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
for(AbstractToken t : expression ){
|
||||
b.append(t.toString());
|
||||
}
|
||||
System.out.println(b.toString());
|
||||
|
||||
}
|
||||
|
||||
}
|
60
DEV3.4/ControleMachine/test/ExempleSY1.java
Normal file
60
DEV3.4/ControleMachine/test/ExempleSY1.java
Normal file
@@ -0,0 +1,60 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class ExempleSY1{
|
||||
public static void main(String[] args){
|
||||
// 3 + 4 * 2
|
||||
// doit donner 342*+
|
||||
ArrayDeque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
|
||||
ShuntingYard se1 = new ShuntingYard(expression);
|
||||
ShuntingYard se2 = new ShuntingYard(expression.clone());
|
||||
// à la main
|
||||
System.out.println("-----à la main -----");
|
||||
System.out.println(se1);
|
||||
se1.shuntFromInput(); //step1
|
||||
System.out.println(se1);
|
||||
se1.pushToStack(); //step2
|
||||
System.out.println(se1);
|
||||
se1.shuntFromInput(); //step3
|
||||
System.out.println(se1);
|
||||
se1.pushToStack(); //step4
|
||||
System.out.println(se1);
|
||||
se1.shuntFromInput(); //step5
|
||||
System.out.println(se1);
|
||||
se1.shuntFromStack(); //step6
|
||||
System.out.println(se1);
|
||||
se1.shuntFromStack(); //step7
|
||||
System.out.println(se1);
|
||||
System.out.println("-----------FIN à la main---------------");
|
||||
|
||||
// avec l'algo
|
||||
System.out.println("-----avec l'algo -----");
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
se2.shunting();
|
||||
System.out.println(se2);
|
||||
|
||||
// se2.shunting();
|
||||
// System.out.println(se2);
|
||||
// se2.shunting();
|
||||
// System.out.println(se2);
|
||||
}
|
||||
}
|
||||
|
43
DEV3.4/ControleMachine/test/ExempleSY2.java
Normal file
43
DEV3.4/ControleMachine/test/ExempleSY2.java
Normal file
@@ -0,0 +1,43 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class ExempleSY2{
|
||||
public static void main(String[] args){
|
||||
// 3 + 4 * 2 − 1
|
||||
// doit donner 342*+1-
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenOperator(Operator.SUB2));
|
||||
expression.addLast(new TokenConstant(1));
|
||||
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
|
||||
}
|
||||
}
|
||||
|
48
DEV3.4/ControleMachine/test/ExempleSY3.java
Normal file
48
DEV3.4/ControleMachine/test/ExempleSY3.java
Normal file
@@ -0,0 +1,48 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class ExempleSY3{
|
||||
public static void main(String[] args){
|
||||
// 3 + 4 × (2 − 1)
|
||||
// doit donner 3421-*+
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenOperator(Operator.SUB2));
|
||||
expression.addLast(new TokenConstant(1));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
}
|
||||
}
|
||||
|
105
DEV3.4/ControleMachine/test/ExempleSY4.java
Normal file
105
DEV3.4/ControleMachine/test/ExempleSY4.java
Normal file
@@ -0,0 +1,105 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
|
||||
|
||||
public class ExempleSY4{
|
||||
public static void main(String[] args){
|
||||
// utilisation de l'algo de Fortan sur l'expression de ExempleSY3
|
||||
// (( 3 ))+(( 4 )*( ( (( 2 ))-(( 1)))))
|
||||
// doit donner 3421-*+ mais le parseur actuel ne sait pas gérer plusieurs parenthèses.
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenOperator(Operator.SUB2));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(1));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
}
|
||||
}
|
||||
|
73
DEV3.4/ControleMachine/test/ExempleSY5.java
Normal file
73
DEV3.4/ControleMachine/test/ExempleSY5.java
Normal file
@@ -0,0 +1,73 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class ExempleSY5{
|
||||
public static void main(String[] args){
|
||||
// 3 + 4 * 2 / ( 1 − 5 ) ^ 2 ^ 3
|
||||
// doit donner 342*15-23^^/+
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenOperator(Operator.DIV));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(1));
|
||||
expression.addLast(new TokenOperator(Operator.SUB2));
|
||||
expression.addLast(new TokenConstant(5));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
expression.addLast(new TokenOperator(Operator.EXP));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenOperator(Operator.EXP));
|
||||
expression.addLast(new TokenConstant(3));
|
||||
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
|
||||
}
|
||||
}
|
||||
|
35
DEV3.4/ControleMachine/test/Operator.java
Normal file
35
DEV3.4/ControleMachine/test/Operator.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Enum pour représenter les opérations sur les entiers (pas d'autre type manipulé pour l'instant).
|
||||
*
|
||||
* Attention : l'ordre de l'énumération sert à coder la précédence des opérateurs.
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*/
|
||||
|
||||
|
||||
public enum Operator {
|
||||
SUB1 ("-", true),
|
||||
EXP ("^", false),
|
||||
MUL ("*", true),
|
||||
DIV ("/", true),
|
||||
ADD ("+", true),
|
||||
SUB2 ("-", true);
|
||||
|
||||
private final String str; // String in original program
|
||||
|
||||
private final boolean isLeftAssociative;
|
||||
|
||||
public boolean isLeftAssociative(){
|
||||
return isLeftAssociative;
|
||||
}
|
||||
|
||||
private Operator(String str, boolean b){
|
||||
this.str=str;
|
||||
this.isLeftAssociative=b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.str;
|
||||
}
|
||||
}
|
214
DEV3.4/ControleMachine/test/Questions.md
Normal file
214
DEV3.4/ControleMachine/test/Questions.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Questions.
|
||||
ce fichier sert à indiquer les réponses après chaque question, indiquez aussi svp vos nom et prénom.
|
||||
il faut rédiger au format markdown svp.
|
||||
En particulier, le code est à mettre entre deux triple quotes.
|
||||
|
||||
Les sources sont disponibles en ligne sur le site des TPs.
|
||||
|
||||
Vous devez rendre sur devoir une archive tar.gz contenant un répertoire test/ contenant les fichiers java (pas les .class) et ce fichier Questions.md.
|
||||
|
||||
```bash
|
||||
tar -czvf test.tar.gz test/
|
||||
```
|
||||
|
||||
Nom : Pourchot
|
||||
Prénom : Adrian
|
||||
|
||||
|
||||
## Programmation défensive.
|
||||
|
||||
1. [2 points] Préparez la javadoc pour les 4 méthodes suivantes de ShuntingYard
|
||||
shuntFromInput()
|
||||
shuntFromStack()
|
||||
pushToStack()
|
||||
crushParenthesis()
|
||||
|
||||
Il faut prévoir un comportement adapté en cas de problème.
|
||||
Par exemple shuntFromInput ne devrait transférer que des TokenConstant et des TokenVariable
|
||||
et pushToStack ne devrait transférer que des TokenOperator ou des parenthèse gauche.
|
||||
|
||||
Indiquez la javadoc dans ce fichier juste après cette ligne, en recopiant la première ligne de déclaration de chaque méthode.
|
||||
|
||||
---
|
||||
```java
|
||||
/**
|
||||
* Envoie la premiere constante ou variables de la file d'entrée vers la file de sortie.
|
||||
* Si le Token récupéré n'est pas TokenConstant ou un TokenVariable, il y a 2 cas possible:
|
||||
* Soit il s'agit d'un TokenOperator ou d'un TokenSeparator de gauche, dans ce cas on replace l'élément extrait au départ de la file d'entrée
|
||||
* puis on fait appel à la méthode shuntFromStack() plutôt que celle-ci.
|
||||
* Soit il s'agit d'un TokenSeparator de droite, dans ce cas on la replace au départ de ola file d'entrée et on fait appel à la méthode crushParenthesis()
|
||||
* pour la supprimer.
|
||||
*/
|
||||
public void shuntFromInput() {
|
||||
|
||||
/**
|
||||
* Envoie le dernier élément de la pile stack vers la file de sortie.
|
||||
*/
|
||||
public void shuntFromStack() {
|
||||
|
||||
/**
|
||||
* Envoie le premier opérateur ou parenthèse gauche de la file d'entrée vers la pile stack.
|
||||
* Si le Token récupéré n'est pas un TokenOperator ou un TokenSeparator de gauche, il y a 2 cas possible:
|
||||
* Soit le Token est un TokenConstant ou un TokenVariable, dans ce cas on replace le Token extrait au départ de la file d'entrée
|
||||
* puis on fait appel à la méthode shuntFromInput() plutôt que celle-ci.
|
||||
* Soit il s'agit d'un TokenSeparator de droite, dans ce cas on la replace au départ de ola file d'entrée et on fait appel à la méthode crushParenthesis()
|
||||
* pour la supprimer.
|
||||
*/
|
||||
public void pushToStack(){
|
||||
|
||||
/**
|
||||
* Supprime le premier élément de la file d'entrée et le dernier de la pile stack.
|
||||
* @exception IllegalStateException Renvoyer si il y s'agit d'un cas particulier.
|
||||
*/
|
||||
public void crushParenthesis(){
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
2. [2 points] Proposez le changement adapté au code de shuntFromInput et de pushToStack
|
||||
|
||||
donnez le code ci-dessous.
|
||||
|
||||
---
|
||||
|
||||
public void shuntFromInput() {
|
||||
x=this.input.getFirst();
|
||||
if(x instanceof(TokenConstant)||x instanceof(TokenVariable))
|
||||
this.output.addLast(x);
|
||||
else if(x instanceof(TokenOperator)){
|
||||
this.input.addFirst(x);
|
||||
shuntFromStack();
|
||||
}
|
||||
else if(x.getSeparator().equals(Separator.LB)){
|
||||
this.input.addFirst(x);
|
||||
shuntFromStack();
|
||||
}
|
||||
else{
|
||||
this.input.addFirst(x);
|
||||
crushParenthesis();
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
## Invariant
|
||||
3. [2 points] Quels sont les invariants des méthodes suivantes?
|
||||
shuntFromInput()
|
||||
shuntFromStack()
|
||||
pushToStack()
|
||||
---
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Debug
|
||||
4. [1 point] Faite tourner les tests avec le fichier JUnit fourni (TestShuntingYard1.java)
|
||||
Quels tests sont passés avec succès?
|
||||
Quels tests ne sont pas passés avec succès?
|
||||
---
|
||||
|
||||
Test réussi:
|
||||
|
||||
1) pushStack(TestShuntingYard1)
|
||||
|
||||
|
||||
Test échoué:
|
||||
|
||||
1) shuntingTest1(TestShuntingYard1)
|
||||
2) shuntInput(TestShuntingYard1)
|
||||
3) shuntStack(TestShuntingYard1)
|
||||
4) CandyCrush(TestShuntingYard1)
|
||||
|
||||
---
|
||||
|
||||
5. [7 points] Pour chaque test non passé, indiquez le bug que vous observez en français.
|
||||
Puis pour chaque test non passé, proposez un changement de code.
|
||||
|
||||
Il faut indiquer le numéro de la ligne dans le fichier initial (vous pouvez le renommer en ajoutant OLD au bout avant de changer le fichier dans une copie).
|
||||
recopier la ligne, puis indiquez en dessous la nouvelle ligne.
|
||||
Il faut expliquer en français dans un commentaire ci-dessous en quoi ce changement consiste.
|
||||
Dans le fichier changé, il faut ajouter en commentaire à la fin //BUGFIX 0 où le numéro correspond à la notation ci-dessous.
|
||||
En dessous je vous donne une exemple en cadeau.
|
||||
|
||||
---
|
||||
|
||||
### Test concerné :
|
||||
aucun, ceci est un BUGFIX gratuit pour indiquer le format attendu
|
||||
Le test d'arrêt de ShuntingYard est incorrect, car il faut lever l'exception seulement quand l'input et la pile sont vide, pas l'un ou l'autre.
|
||||
|
||||
ShuntingYard.java line 73 (avant):
|
||||
|
||||
```java
|
||||
return (this.input.isEmpty() || this.stack.isEmpty());
|
||||
```
|
||||
|
||||
devient
|
||||
ShuntingYard.java line 73 (après):
|
||||
|
||||
```java
|
||||
return (this.input.isEmpty() && this.stack.isEmpty()); //BUG FIX 0
|
||||
```
|
||||
|
||||
### Test concerné :
|
||||
???
|
||||
|
||||
```java
|
||||
// BUGFIX 1
|
||||
```
|
||||
|
||||
```java
|
||||
// BUGFIX 2
|
||||
```
|
||||
|
||||
---
|
||||
1) shuntingTest1(TestShuntingYard1): On observe que le shunting c'est arrêter car la file d'entrée et la pile stack étaient vide ce qui ne devrait pas être le cas.
|
||||
|
||||
2) shuntInput(TestShuntingYard1): On observe que l'AbstractToken n'est pas trouvé dans la file alors qu'il devrait.
|
||||
|
||||
3) shuntStack(TestShuntingYard1): Même chose que pour shuntInput, un AbstractToken n'est pas trouvé dans la pile alors qu'il devrait.
|
||||
|
||||
4) CandyCrush(TestShuntingYard1): On observe qu'une parenthèse droite est trouvé alors qu'il devrait s'agir d'une parenthèse gauche.
|
||||
|
||||
|
||||
---
|
||||
|
||||
6. [6 points] Complétez le fichier de test TestShuntingYard2.java
|
||||
|
||||
a) [1 point] Proposez un test JUnit pour attraper un NullPointerException lorsqu'on appelle shuntFromInput() sur un input vide.
|
||||
|
||||
indiquez le nom de ce test ici :
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
b) [1 point] Proposez un test JUnit pour attraper l'exception adaptée lorsqu'on appelle shuntFromInput() sur un input dont le prochain token n'est pas un TokenVariable ou un TokenConstant.
|
||||
|
||||
indiquez le nom de ce test ici :
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
c) [2 points] Pour l'exemple ExempleSY2.java, proposez la liste des instructions primitives correspondant à l'algo de Dijkstra.
|
||||
(i.e. les primitives que shunting devrait appeller si code convenablement).
|
||||
|
||||
---
|
||||
|
||||
|
||||
```java
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
d) [3 points]
|
||||
Proposez un test JUnit correspondant à l'exemple ExempleSY2.java
|
||||
Expliquez bien votre démarche.
|
||||
|
||||
indiquez le nom de ce test ici, puis expliquez votre démarche :
|
||||
|
||||
---
|
||||
|
||||
---
|
47
DEV3.4/ControleMachine/test/README.txt
Normal file
47
DEV3.4/ControleMachine/test/README.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
Ce projet concerne l'agorithme de Dijkstra présenté sur wikipedia
|
||||
ici :
|
||||
https://en.wikipedia.org/wiki/Shunting_yard_algorithm
|
||||
|
||||
=================================================================
|
||||
|
||||
Ce projet contient le présent fichier et une image et des fichiers java
|
||||
README.txt descripton des fichiers de ce répertoire
|
||||
Shunting_yard.svg.png image tiré de la page wikipedia de l'algo
|
||||
|
||||
=================================================================
|
||||
Ce projet concerne les fichiers java suivant.
|
||||
|
||||
AbstractToken.java type abstrait pour les token (jeton) d'une expression.
|
||||
TokenConstant.java hérite du précédent, jeton pour les constantes
|
||||
TokenVariable.java jeton pour les variables
|
||||
ReservedWord.java type énuméré pour les mots réservés qui ne peuvent être des noms de variable.
|
||||
TokenOperator.java jeton pour les opérateurs
|
||||
Operator.java type énuméré pour les symboles d'opérateurs, utilisé par TokenOperator
|
||||
TokenSeparator.java jeton pour les séparateurs
|
||||
Separator.java type énuméré pour les symboles de séparateurs, utilisé par TokenSeparator
|
||||
|
||||
Exemple.java exemple d'expression construite
|
||||
|
||||
ShuntingYard.java classe fournissant l'algorithme de parsing de Dijkstra
|
||||
|
||||
ExempleSY1.java exemple d'usage de Shunting Yard
|
||||
ExempleSY2.java exemple d'usage de Shunting Yard
|
||||
ExempleSY3.java exemple d'usage de Shunting Yard
|
||||
ExempleSY4.java exemple d'usage de Shunting Yard
|
||||
ExempleSY5.java exemple d'usage de Shunting Yard
|
||||
|
||||
================================================================
|
||||
Pour l'examen proprement dit.
|
||||
|
||||
Questions.md fichier avec le barème et les questions
|
||||
|
||||
TestShuntingYard1.java fichier de test fourni
|
||||
TestShuntingYard2.java fichier de test à compléter
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
23
DEV3.4/ControleMachine/test/ReservedWord.java
Normal file
23
DEV3.4/ControleMachine/test/ReservedWord.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Enum pour représenter les mots réservés du langage qui ne peuvent pas être des noms de variables.
|
||||
*
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*/
|
||||
|
||||
|
||||
public enum ReservedWord {
|
||||
INT ("int"),
|
||||
FUNC ("function");
|
||||
|
||||
private final String str; // String in original program
|
||||
|
||||
private ReservedWord(String str){
|
||||
this.str=str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.str;
|
||||
}
|
||||
}
|
28
DEV3.4/ControleMachine/test/Separator.java
Normal file
28
DEV3.4/ControleMachine/test/Separator.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Enum pour représenter les "séparateurs" dans le programme.
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*/
|
||||
|
||||
|
||||
public enum Separator {
|
||||
LB ("("),
|
||||
RB (")"),
|
||||
COMMA (","),
|
||||
SCL (";"),
|
||||
LCB ("{"),
|
||||
RCB ("}"),
|
||||
LSB ("["),
|
||||
RSB ("]");
|
||||
|
||||
private final String str; // String in original program
|
||||
|
||||
private Separator(String str){
|
||||
this.str=str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.str;
|
||||
}
|
||||
}
|
273
DEV3.4/ControleMachine/test/ShuntingYard.java
Normal file
273
DEV3.4/ControleMachine/test/ShuntingYard.java
Normal file
@@ -0,0 +1,273 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
/**
|
||||
* Classe implémentant l'algorithme proposé par Dijkstra en 1961 pour transformer une expression en notation infixe, en expression postfixe.
|
||||
* https://en.wikipedia.org/wiki/Shunting_yard_algorithm
|
||||
*
|
||||
* Le constructeur prend en entrée l'entrée de l'algorithme (input) qui sera une file de AbstractToken et initialise
|
||||
* une pile pour les opérateurs et séparateurs, et une file de sortie.
|
||||
* Pour uniformiser, tout est modélisé avec l'interface Deque pour des AbstractToken.
|
||||
*
|
||||
* En pratique les seuls mouvements entre ces trois structures de données sont faits par trois primitives :
|
||||
* shuntFromInput() (input vers output)
|
||||
* shuntFromStack() (stack vers output)
|
||||
* pushToStack() (input vers stack)
|
||||
*
|
||||
* L'algorithme fonctionne par analogie au rangement des wagons dans une gare de triage (shunting yard veut dire gare de triage).
|
||||
*
|
||||
* output ================== input
|
||||
* \\ //
|
||||
* \ /
|
||||
* \/
|
||||
* ||
|
||||
* stack
|
||||
*
|
||||
* Le dessin en ASCII ci-dessus a été qualifié de "Jackson Pollock" du crobar par Luc Hernandez.
|
||||
* Pour un exemple plus explicite : regardez svp le dessin "Shunting_yard.svg.png"
|
||||
*
|
||||
*
|
||||
* Les constantes et les variables sont envoyées de droite à gauche avec shuntFromInput
|
||||
* Les symboles d'opérations ou de séparation sont envoyés sur la pile avec pushToStack
|
||||
* puis envoyés en sortie avec shuntFromStack quand c'est le bon moment.
|
||||
*
|
||||
* pour les opérateurs, en gros tout se décide avec la priorité des opérations
|
||||
* En cas d'égalité on regarde si l'opérateur est associatif à gauche :
|
||||
* ceci est le cas des 4 opérations binaires * \/ + - mais pas de l'exponentiation ^ (associativité à droite).
|
||||
* Ainsi a^b^c sera interprété convenablement comme a^(b^c)
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*/
|
||||
|
||||
|
||||
public class ShuntingYard {
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private Deque<AbstractToken> input;
|
||||
private Deque<AbstractToken> output;
|
||||
private Deque<AbstractToken> stack;
|
||||
|
||||
public ShuntingYard(Deque<AbstractToken> input){
|
||||
this.input = input;
|
||||
this.output = new ArrayDeque<AbstractToken>();
|
||||
this.stack = new ArrayDeque<AbstractToken>();
|
||||
}
|
||||
|
||||
public Deque<AbstractToken> getInput(){
|
||||
return this.input;
|
||||
}
|
||||
|
||||
public Deque<AbstractToken> getOutput(){
|
||||
return this.stack;
|
||||
}
|
||||
|
||||
public Deque<AbstractToken> getStack(){
|
||||
return this.output;
|
||||
}
|
||||
|
||||
|
||||
// input and stack are empty
|
||||
public boolean isOver(){
|
||||
return (this.input.isEmpty() || this.stack.isEmpty()); //BUG FIX 1
|
||||
}
|
||||
|
||||
//
|
||||
// output <---------------- input
|
||||
//
|
||||
//
|
||||
// stack
|
||||
/**
|
||||
* Envoie la premiere constante ou variables de la file d'entrée vers la file de sortie.
|
||||
* Si le Token récupéré n'est pas TokenConstant ou un TokenVariable, il y a 2 cas possible:
|
||||
* Soit il s'agit d'un TokenOperator ou d'un TokenSeparator de gauche, dans ce cas on replace l'élément extrait au départ de la file d'entrée
|
||||
* puis on fait appel à la méthode shuntFromStack() plutôt que celle-ci.
|
||||
* Soit il s'agit d'un TokenSeparator de droite, dans ce cas on la replace au départ de la file d'entrée et on fait appel à la méthode crushParenthesis()
|
||||
* pour la supprimer.
|
||||
*/
|
||||
public void shuntFromInput() {
|
||||
x=this.input.getFirst();
|
||||
if(x instanceof(TokenConstant)||x instanceof(TokenVariable))
|
||||
this.output.addLast(x);
|
||||
else if(x instanceof(TokenOperator)){
|
||||
this.input.addFirst(x);
|
||||
shuntFromStack();
|
||||
}
|
||||
else if(x.getSeparator().equals(Separator.LB)){
|
||||
this.input.addFirst(x);
|
||||
shuntFromStack();
|
||||
}
|
||||
else{
|
||||
this.input.addFirst(x);
|
||||
crushParenthesis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// output <--- input
|
||||
// \
|
||||
// |
|
||||
// stack
|
||||
/**
|
||||
* Envoie le dernier élément de la pile stack vers la file de sortie.
|
||||
*/
|
||||
public void shuntFromStack() {
|
||||
this.output.addFirst(this.stack.removeLast());
|
||||
}
|
||||
|
||||
// output ---------- input
|
||||
// /
|
||||
// V
|
||||
// stack
|
||||
/**
|
||||
* Envoie le premier opérateur ou parenthèse gauche de la file d'entrée vers la pile stack.
|
||||
* Si le Token récupéré n'est pas un TokenOperator ou un TokenSeparator de gauche, il y a 2 cas possible:
|
||||
* Soit le Token est un TokenConstant ou un TokenVariable, dans ce cas on replace le Token extrait au départ de la file d'entrée
|
||||
* puis on fait appel à la méthode shuntFromInput() plutôt que celle-ci.
|
||||
* Soit il s'agit d'un TokenSeparator de droite, dans ce cas on la replace au départ de ola file d'entrée et on fait appel à la méthode crushParenthesis()
|
||||
* pour la supprimer.
|
||||
*/
|
||||
public void pushToStack(){
|
||||
this.stack.addFirst(this.input.getFirst());
|
||||
}
|
||||
|
||||
// output ) input
|
||||
// ^
|
||||
// ( <------| both to be destroyed
|
||||
// stack
|
||||
//
|
||||
// throws IllegalStateException si ce n'est pas exactement ce cas.
|
||||
/**
|
||||
* Supprime le premier élément de la file d'entrée et le dernier de la pile stack.
|
||||
* @exception IllegalStateException Renvoyer si il y s'agit d'un cas particulier.
|
||||
*/
|
||||
public void crushParenthesis(){
|
||||
this.stack.removeLast();
|
||||
this.input.removeFirst();
|
||||
}
|
||||
|
||||
// does one step of Dijkstra Shunting algorithm
|
||||
// if is is done it throws the exception
|
||||
public void shunting(){
|
||||
if (isOver()) throw new IllegalStateException("the shunting is over, since both the input and the stack are empty.");
|
||||
else if (this.input.isEmpty()){
|
||||
if (this.stack.getFirst() instanceof TokenSeparator){
|
||||
TokenSeparator s = (TokenSeparator) this.stack.getFirst();
|
||||
if (s.getSeparator().equals(Separator.LB)){
|
||||
throw new IllegalArgumentException("the shunting is over with a parenthesis mismatch extra left bracket");}
|
||||
}
|
||||
else // should be an operator
|
||||
shuntFromStack();
|
||||
}
|
||||
else if (this.input.getFirst() instanceof TokenConstant) {
|
||||
shuntFromInput();
|
||||
shuntFromInput();
|
||||
}
|
||||
// else
|
||||
if (this.input.getFirst() instanceof TokenVariable) {
|
||||
shuntFromInput();
|
||||
}
|
||||
else if (this.input.getFirst() instanceof TokenSeparator) {
|
||||
TokenSeparator s = (TokenSeparator) this.input.getFirst();
|
||||
// test si LB left bracket
|
||||
if (s.getSeparator().equals(Separator.LB)){
|
||||
pushToStack();
|
||||
}
|
||||
else if (s.getSeparator().equals(Separator.RB)){
|
||||
if(stack.isEmpty()) throw new IllegalArgumentException("the shunting is over with a parenthesis mismatch extra right bracket");
|
||||
else {
|
||||
if (this.stack.getFirst() instanceof TokenOperator){
|
||||
shuntFromStack(); // should be the operator concerned by parenthesis
|
||||
}
|
||||
else {// it is a separator
|
||||
crushParenthesis(); // we discard the parenthesis.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.input.getFirst() instanceof TokenOperator) {
|
||||
if (this.stack.isEmpty()){
|
||||
pushToStack();
|
||||
}
|
||||
else if (this.stack.getFirst() instanceof TokenSeparator){
|
||||
TokenSeparator s = (TokenSeparator) this.stack.getFirst();
|
||||
pushToStack();
|
||||
}
|
||||
else if (this.stack.getFirst() instanceof TokenOperator){
|
||||
TokenOperator o = (TokenOperator) this.input.getFirst();
|
||||
TokenOperator o2 = (TokenOperator) this.stack.getFirst();
|
||||
if (o2.takesPrecedenceOver(o)){
|
||||
shuntFromStack();
|
||||
}
|
||||
else pushToStack();// shuntFromInput();// input takes precedence
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("\t\t\t\t");
|
||||
for(AbstractToken t : this.input ){
|
||||
b.append(t.toString());
|
||||
}
|
||||
b.append(" :input\noutput: ");
|
||||
for(AbstractToken t : this.output ){
|
||||
b.append(t.toString());
|
||||
}
|
||||
b.append("\n\t\t stack: ");
|
||||
for(AbstractToken t : this.stack ){
|
||||
b.append(t.toString());
|
||||
}
|
||||
b.append("\n");
|
||||
b.append("--------------------------------------------------------------\n");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args){
|
||||
// 3 + 4 × (2 − 1)
|
||||
// pas de parenthèse encore, je fais 3 + 4 * 2
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenOperator(Operator.SUB2));
|
||||
expression.addLast(new TokenConstant(1));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
System.out.println(se);
|
||||
se.shunting();
|
||||
}
|
||||
|
||||
}
|
||||
|
BIN
DEV3.4/ControleMachine/test/Shunting_yard.svg.png
Normal file
BIN
DEV3.4/ControleMachine/test/Shunting_yard.svg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
179
DEV3.4/ControleMachine/test/TestShuntingYard1.java
Normal file
179
DEV3.4/ControleMachine/test/TestShuntingYard1.java
Normal file
@@ -0,0 +1,179 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
import static org.junit.Assert.assertTrue; // import static : une facilité offerte depuis java5 (pas besoin de mettre le préfixe)
|
||||
import static org.junit.Assert.assertFalse; //
|
||||
import static org.junit.Assert.assertSame; //
|
||||
import static org.junit.Assert.assertNotSame; //
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Une classe pour faire des tests sur la classe ShuntingYard avec JUnit
|
||||
*/
|
||||
public class TestShuntingYard1 {
|
||||
|
||||
|
||||
/**
|
||||
* ShuntInput déplace un token depuis input vers output
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void shuntInput(){
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
AbstractToken t1 = se.getInput().getFirst();
|
||||
se.shuntFromInput();
|
||||
AbstractToken t2 = se.getOutput().getLast();
|
||||
assertSame(t1,t2);
|
||||
}
|
||||
|
||||
/**
|
||||
* PushStack déplace un token depuis input vers stack
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void pushStack(){
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
se.shuntFromInput();
|
||||
AbstractToken t1 = se.getInput().getFirst();
|
||||
se.pushToStack();
|
||||
AbstractToken t2 = se.getStack().getFirst();
|
||||
assertSame(t1,t2);
|
||||
}
|
||||
|
||||
/**
|
||||
* ShuntFromStack déplace un token depuis stack vers output
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void shuntStack(){
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
se.shuntFromInput();
|
||||
se.pushToStack();
|
||||
se.shuntFromInput();
|
||||
AbstractToken t1 = se.getStack().getFirst();
|
||||
se.shuntFromStack();
|
||||
AbstractToken t2 = se.getOutput().getLast();
|
||||
assertSame(t1,t2);
|
||||
}
|
||||
|
||||
/**
|
||||
* crushParenthesis écrase les parenthèses quand stack est une LB
|
||||
* et input est un RB
|
||||
*/
|
||||
@Test
|
||||
public void CandyCrush(){
|
||||
Deque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenSeparator(Separator.LB));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
expression.addLast(new TokenOperator(Operator.SUB2));
|
||||
expression.addLast(new TokenConstant(1));
|
||||
expression.addLast(new TokenSeparator(Separator.RB));
|
||||
ShuntingYard se = new ShuntingYard(expression);
|
||||
se.pushToStack();
|
||||
se.shuntFromInput();
|
||||
se.pushToStack();
|
||||
se.shuntFromInput();
|
||||
se.shuntFromStack();
|
||||
//prêt pour enlever les parenthèses.
|
||||
AbstractToken t1 = se.getStack().getFirst();
|
||||
TokenSeparator s1 = (TokenSeparator) t1;
|
||||
int sizeStackbefore = se.getStack().size();
|
||||
AbstractToken t2 = se.getInput().getFirst();
|
||||
TokenSeparator s2 = (TokenSeparator) t2;
|
||||
int sizeInputbefore = se.getInput().size();
|
||||
assertEquals(Separator.LB,s1.getSeparator());
|
||||
assertEquals(Separator.RB,s2.getSeparator());
|
||||
se.crushParenthesis();
|
||||
int sizeStackafter = se.getStack().size();
|
||||
int sizeInputafter = se.getInput().size();
|
||||
assertEquals(sizeStackbefore-1,sizeStackafter);
|
||||
assertEquals(sizeInputbefore-1,sizeInputafter);
|
||||
}
|
||||
|
||||
/**
|
||||
* shunbtingTest1 vérifie que tout se passe bien pour l'exemple de ExempleSY1
|
||||
*/
|
||||
@Test
|
||||
public void shuntingTest1(){
|
||||
ArrayDeque<AbstractToken> expression = new ArrayDeque<AbstractToken>();
|
||||
expression.addLast(new TokenConstant(3));
|
||||
expression.addLast(new TokenOperator(Operator.ADD));
|
||||
expression.addLast(new TokenConstant(4));
|
||||
expression.addLast(new TokenOperator(Operator.MUL));
|
||||
expression.addLast(new TokenConstant(2));
|
||||
|
||||
// moralement on veut tester que les trois structures de données sont les mêmes de manière synchrone entre ceci
|
||||
// ShuntingYard se1 = new ShuntingYard(expression);
|
||||
// se1.shuntFromInput(); //step1
|
||||
// se1.pushToStack(); //step2
|
||||
// se1.shuntFromInput(); //step3
|
||||
// se1.pushToStack(); //step4
|
||||
// se1.shuntFromInput(); //step5
|
||||
// se1.shuntFromStack(); //step6
|
||||
// se1.shuntFromStack(); //step7
|
||||
// et cela
|
||||
// ShuntingYard se2 = new ShuntingYard(expression);
|
||||
// se2.shunting(); //step1
|
||||
// Pour tester on utilise la facilité permettant de comparer élément pas élément deux tableaux.
|
||||
// assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
// assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
// assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
ShuntingYard se1 = new ShuntingYard(expression);
|
||||
ShuntingYard se2 = new ShuntingYard(expression.clone());// on clone l'expression, car sinon l'input est le même pour les deux exemples
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.shuntFromInput(); //step1
|
||||
se2.shunting(); //step1
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.pushToStack(); //step2
|
||||
se2.shunting(); //step2
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.shuntFromInput(); //step3
|
||||
se2.shunting(); //step3
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.pushToStack(); //step4
|
||||
se2.shunting(); //step4
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.shuntFromInput(); //step5
|
||||
se2.shunting(); //step5
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.shuntFromStack(); //step6
|
||||
se2.shunting(); //step6
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
se1.shuntFromStack(); //step7
|
||||
se2.shunting(); //step7
|
||||
assertArrayEquals("Inputs are not the same",se1.getInput().toArray(),se2.getInput().toArray());
|
||||
assertArrayEquals("stacks are not the same",se1.getStack().toArray(),se2.getStack().toArray());
|
||||
assertArrayEquals("Output are not the same",se1.getOutput().toArray(),se2.getOutput().toArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
22
DEV3.4/ControleMachine/test/TestShuntingYard2.java
Normal file
22
DEV3.4/ControleMachine/test/TestShuntingYard2.java
Normal file
@@ -0,0 +1,22 @@
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
import static org.junit.Assert.assertTrue; // import static : une facilité offerte depuis java5 (pas besoin de mettre le préfixe)
|
||||
import static org.junit.Assert.assertFalse; //
|
||||
import static org.junit.Assert.assertSame; //
|
||||
import static org.junit.Assert.assertNotSame; //
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Une classe pour faire des tests sur la classe ShuntingYard avec JUnit
|
||||
*/
|
||||
public class TestShuntingYard2 {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
30
DEV3.4/ControleMachine/test/TokenConstant.java
Normal file
30
DEV3.4/ControleMachine/test/TokenConstant.java
Normal file
@@ -0,0 +1,30 @@
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Jeton pour les constantes
|
||||
*
|
||||
* sert uniquement aux entiers, pas d'autre type pour l'instant
|
||||
*
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*/
|
||||
|
||||
public class TokenConstant extends AbstractToken {
|
||||
|
||||
private int value;
|
||||
|
||||
public TokenConstant (int i){
|
||||
Objects.requireNonNull(i, "i must not be null");
|
||||
this.value=i;
|
||||
}
|
||||
|
||||
public int getValue(){
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return String.valueOf(this.value);
|
||||
}
|
||||
}
|
||||
|
39
DEV3.4/ControleMachine/test/TokenOperator.java
Normal file
39
DEV3.4/ControleMachine/test/TokenOperator.java
Normal file
@@ -0,0 +1,39 @@
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Jeton pour les opérateurs
|
||||
*
|
||||
* sert uniquement à des opérations entières, pas d'autre type pour l'instant.
|
||||
*
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
* @see Operators.java
|
||||
*/
|
||||
|
||||
|
||||
public class TokenOperator extends AbstractToken{
|
||||
|
||||
private Operator o;
|
||||
|
||||
public TokenOperator(Operator o){
|
||||
Objects.requireNonNull(o, "o must not be null");
|
||||
this.o=o;
|
||||
}
|
||||
|
||||
public Operator getOperator(){
|
||||
return this.o;
|
||||
}
|
||||
|
||||
public boolean takesPrecedenceOver(TokenOperator to2){
|
||||
return (this.o.ordinal() < to2.getOperator().ordinal()
|
||||
||
|
||||
((this.o.ordinal() == to2.getOperator().ordinal())
|
||||
&&
|
||||
to2.getOperator().isLeftAssociative()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.o.toString();
|
||||
}
|
||||
}
|
30
DEV3.4/ControleMachine/test/TokenSeparator.java
Normal file
30
DEV3.4/ControleMachine/test/TokenSeparator.java
Normal file
@@ -0,0 +1,30 @@
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Jeton pour les séparateurs
|
||||
*
|
||||
* parenthèses pour des expressions, etc.
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
* @see Separator.java
|
||||
*/
|
||||
|
||||
|
||||
public class TokenSeparator extends AbstractToken{
|
||||
|
||||
private Separator s;
|
||||
|
||||
public TokenSeparator(Separator s){
|
||||
Objects.requireNonNull(s, "s must not be null");
|
||||
this.s=s;
|
||||
}
|
||||
|
||||
public Separator getSeparator(){
|
||||
return this.s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.s.toString();
|
||||
}
|
||||
}
|
49
DEV3.4/ControleMachine/test/TokenVariable.java
Normal file
49
DEV3.4/ControleMachine/test/TokenVariable.java
Normal file
@@ -0,0 +1,49 @@
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Jeton pour les variables
|
||||
*
|
||||
* sert uniquement à des variables entières, pas d'autre type pour l'instant.
|
||||
*
|
||||
*
|
||||
* The general rules for naming variables are:
|
||||
*
|
||||
* Names can contain letters and digits
|
||||
* Names must begin with a letter
|
||||
* Names should start with a lowercase letter, and cannot contain whitespace
|
||||
* Names are case-sensitive ("myVar" and "myvar" are different variables)
|
||||
* Reserved words cannot be used as names
|
||||
*
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
* @see ReservedWords.java
|
||||
*/
|
||||
|
||||
|
||||
public class TokenVariable extends AbstractToken {
|
||||
|
||||
private final static String regexp="[a-z][0-9a-zA-Z]*";
|
||||
|
||||
private String variableName; // String in original program
|
||||
|
||||
public TokenVariable (String s){
|
||||
Objects.requireNonNull(s, "s must not be null");
|
||||
for (ReservedWord k : ReservedWord.values()){
|
||||
if (k.toString().equals(s)){
|
||||
throw new IllegalArgumentException("Illegal variable name, attempt to use reserved keyword " + k.toString());
|
||||
}
|
||||
}
|
||||
if (! s.matches(this.regexp)){
|
||||
throw new IllegalArgumentException("Illegal variable name, name should start with a lower case letter followed potentially by digits or other letters lower or upper case.");
|
||||
}
|
||||
else {
|
||||
this.variableName=s;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.variableName;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user