CentraleSupélec LRI
Département informatique Équipe MODHEL
Bât Breguet, 3 rue Joliot-Curie Bât 650 Ada Lovelace, Université Paris Sud
91190 Gif-sur-Yvette, France Rue Noetzlin, 91190 Gif-sur-Yvette, France
Enseignement

Table des matières

Exemples de code, techniques de programmation Exemples

Des exemples montrant comment résoudre des problèmes récurrents en Java : lire et écrire dans un fichier, créer une interface graphique, sélectionner un fichier, lire et écrire un fichier XML etc.

Une page sur l'utilisation de Greenfoot avec ou sans Eclipse

Exemples et documentation pour le cours de troisième année Concepts des langages et techniques de programmation

Première année CentraleSupélec 1ère année CS

SIP SIP

Deuxième année 2ème année

Projets de développement logiciel Projets

Projets pour la séquence 5 en 2018-2019 (identification nécessaire avec votre nom d'utilisateur et mot de passe Supélec)

Voir les consignes pour les élèves dont j'encadre le projet.

Troisième année 3ème année

Modélisation des systèmes Modélisation

7 cours, 1 bureau d'étude (+6 cours et 1 bureau d'étude par Lina Ye)

Objectif

Ce module présente les techniques de modélisation des systèmes qui permettent de concevoir un système informatique, de simuler son fonctionnement ainsi que l’environnement dans lequel il devra fonctionner, et de générer son code pour une plateforme. L’accent est mis sur la disponibilité de différents modèles adaptés aux différentes parties d’un système et sur la possibilité d’utiliser conjointement ces modèles.

Programme

  • Modélisation, abstraction
    Modèles et interprétation des modèles. Modèles exécutables, calculables, prédictifs, explicatifs. Modèles classiques: temps continu, temps discret périodique, flots de données synchrones, événements discrets, automates hiérarchiques, systèmes réactifs synchrones.
  • Modélisation et validation
    Ordonnancement, Allocation de ressources (CPU, mémoire). Vérifications formelles: propriétés mathématiques des modèles, preuves, model-checking, application à la sûreté de fonctionnement.
  • Ingénierie dirigée par les modèles
    Relations entre systèmes, modèles et métamodèles
    Définition d'un langage de modélisation (DSL), transformations de modèles
  • Hétérogénéité et interactions entre modèles
    Hiérarchies de modèles. Problèmes aux limites entre modèles: continu/discret, flots de données/événements. Systèmes modaux.
  • Application à la modélisation d’un système
    Approche réactive synchrone pour le contrôle + preuve formelle, approche à flots de données pour les traitements, temps continu pour la modélisation de l’environnement du système.

Transparents du cours

Les transparents :

Cours sur machine : métamodèles, modèles et transformations de modèle.

Une version ancienne du polycopié du cours est également disponible.

Bureau d'étude

Le sujet du bureau d'étude (création d'un DSL)

Sémantique des langages Sémantique

5 cours, 1 bureau d'étude

Bureau d'étude preuve de programmes avec Krakatoa/Why

Objectif

Ce module présente différentes techniques permettant de définir la sémantique d'un langage de programmation.

Programme

  • Syntaxe concrète, syntaxe abstraite
  • Syntaxe abstraite et sémantique
  • Sémantique traductionnelle
  • Sémantique opérationnelle (petits et grands pas)
  • Sémantique dénotationnelle
  • Sémantique axiomatique
  • Sémantique des définitions récursives
  • Application au langage Niklaus

À partir de 2015, les définitions sémantiques sont faites en Isabelle/HOL.

Ressources :

  • Tutoriel : définition d'un type liste et preuve de théorèmes
  • Niklaus : le langage repris du cours de traitement des langages et ses différents styles de sémantique.

Obsolète depuis septembre 2018

Première année du cursus ingénieur Supélec 1ère année

Architecture des ordinateurs ARCHI

7 cours, 3 séances de travaux dirigés, 2 séances d'études de laboratoire

Voir le site du cours pour plus de détails.

Génie logiciel

Premier TD, nombre secret

package jeu;

import java.util.Scanner;

public class NombreSecret {
	/** Valeur max du nombre à deviner */
	private static int MAX_VAL = 100;
	/** Nombre maximal d'essais */
	private static int MAX_TRY = 5;

	public static void main(String[] args) {
		// Scanner pour lire les entiers sur la console
		Scanner sin = new Scanner(System.in);
		// Est-ce que l'utilisateur n'a plus envie de jouer
		boolean done = false;

		// Tant que l'utilisateur ne veut pas s'arrêter
		while (!done) {
			// Tableau pour mémoriser les essais de l'utilisateur
			int[] guesses = new int[MAX_TRY];
			// L'utilisateur a-t-il trouvé ?
			boolean found = false;
			// Nombre de tentatives
			int attempts = 0;
			// Génération du nombre secret
			int rnd = generateRandomInt(0, MAX_VAL);

			// Tant que l'utilisateur n'a pas deviné et n'a pas fait trop de tentatives...
			while ((!found) && (attempts < MAX_TRY)) {
				System.out.println("Devinez le nombre secret (-1 pour arrêter) : ");
				int val = sin.nextInt();
				if (val == -1) {
					// Si l'utilisateur a entré -1, on sort de la boucle while
					break;
				}
				guesses[attempts] = val;
				attempts++;
				// checkResponse nous indique si l'utilisateur a trouvé le nombre
				found = checkResponse(rnd, val);
			}

			if (found) {
				System.out.println("Trouvé en " + attempts + " tentatives.");
			} else if (attempts == MAX_TRY) {
				System.out.println("Nombre maximal de tentatives (" + attempts + ") dépassé.");
				System.out.println("Le nombre était " + rnd + ".");
			} else {
				System.out.println("Abandon.");
				System.out.println("Le nombre était " + rnd + ".");
			}
			// On affiche les tentatives successives
			System.out.println("Essais :");
			for (int i = 0; i < attempts; i++) {
				System.out.print(guesses[i] + " ");
			}
			System.out.println();

			// On demande à l'utilisateur s'il veut rejouer
			System.out.println("Voulez-vous rejouer [o/n] : ");
			// On lit sa réponse (chaîne de caractères)
			String answer = sin.next();
			// Si la réponse n'est pas vide et commence par un 'o' quand on la met en
			// minuscules
			if ((answer.length() > 0) && (answer.toLowerCase().charAt(0) == 'o')) {
				// c'est qu'il ne veut pas s'arrêter
				done = false;
			} else {
				// sinon, il veut s'arrêter
				done = true;
			}
		}
		// On ferme le Scanner maintenant qu'on n'en a plus besoin
		sin.close();
	}

	/** Génère un entier aléatoire dans [min, max[ */
	public static int generateRandomInt(int min, int max) {
		double rnd = Math.random();
		return (int) (min + (max - min) * rnd);
	}

	/**
	 * Vérifie la réponse de l'utilisateur et affiche un message selon qu'il a
	 * trouvé le nombre, proposé un valeur trop petite ou trop grande. Rend true si
	 * l'utilisateur a deviné, false sinon.
	 */
	public static boolean checkResponse(int rnd, int val) {
		if (val == rnd) {
			System.out.println("Gagné !");
			return true;
		}
		if (val < rnd) {
			System.out.println("Trop petit...");
		} else {
			System.out.println("Trop grand...");
		}
		return false;
	}
}

Premier BE (TDs 2 et 3)

/**
 * Représente un rationnel sous la forme (numérateur/dénominateur).
 */
public class Rational {
	/** Numérateur */
	private int numerator;
	/** Dénominateur */
	private int denominator;

	/** Initialise un nouveau rationnel num/den */
	public Rational(int num, int den) {
		this.numerator = num;
		this.denominator = den;
	}

	/** Indique si ce rationnel est nul. */
	public boolean isNull() {
		return this.numerator == 0;
	}

	/** Indique si ce rationnel est égal à 1. */
	public boolean isOne() {
		return this.numerator == this.denominator;
	}

	/** Rend un nouveau rationnel, somme de ce rationnel et de r. */
	public Rational add(Rational r) {
		int num = this.numerator * r.denominator
				+ r.numerator * this.denominator;
		int den = this.denominator * r.denominator;
		return new Rational(num, den);
	}

	/** Rend un nouveau rationnel, produit de ce rationnel et de r. */
	public Rational multiply(Rational r) {
		int num = this.numerator * r.numerator;
		int den = this.denominator * r.denominator;
		return new Rational(num, den);
	}

	/** Rend un nouveau rationnel, version simplifiée de ce rationnel. */
	public Rational simplify() {
		int gcd = gcd(this.numerator, this.denominator);
		return new Rational(this.numerator / gcd,
				            this.denominator / gcd);
	}

	/** Rend une approximation du rationnel en double. */
	public double approximate() {
		return ((double)numerator) / denominator;
	}

	/** Calcule le PGCD de deux entiers par soustractions successives */
	public static int gcd(int a, int b) {
		// Si l'un des deux entiers est nul, la boucle ne terminera pas
		if (a == 0) {
			return b;
		}
		if (b == 0) {
			return a;
		}
		while (a != b) {
			if (a < b) {
				b = b - a;
			} else {
				a = a - b;
			}
		}
		return a;
	}

	@Override
	/** Rend une chaîne de caractères qi représente ce rationnel. */
	public String toString() {
		if (this.denominator == 1) {
			return Integer.toString(this.numerator);
		}
		if (this.numerator == 0) {
			return "0";
		}
		return Integer.toString(this.numerator) + "/" + Integer.toString(this.denominator);
	}
}
public class RationalTest {
	public static void main(String[] args) {
		Rational q = new Rational(3, 4);
		System.out.println("q = " + q);
		System.out.println("q ≈ " + q.approximate());
		Rational r = new Rational(1, 6);
		System.out.println("r = " + r);
		System.out.println("r ≈ " + r.approximate());
		System.out.println("q+r = " + q.add(r));
		System.out.println("q*r = " + q.multiply(r));
		System.out.println("gcd(12, 18) = " + Rational.gcd(12, 18));
		System.out.println("q+r = " + q.add(r).simplify());
		System.out.println("q*r = " + q.multiply(r).simplify());
	}
}
/**
 * Monômes à coefficient rationnel et degré entier
 */
public class Monomial {
	/** Coefficient du monôme */
	private Rational coef;
	/** Exposant (degré) du monôme. */
	private int degree;

	public Monomial(Rational coef, int degree) {
		if (degree < 0) {
			System.err.println("Erreur : création d'un monôme de degré négatif.");
			System.exit(1);
		}
		this.coef = coef;
		this.degree = degree;
	}

	/** Rend la valeur du monôme pour une valeur de X */
	public Rational evaluate(Rational x) {
		Rational value = new Rational(1,1);
		for (int i = 0; i < degree; i++) {
			value = value.multiply(x);
		}
		return value.multiply(coef).simplify();
	}

	@Override
	public String toString() {
		String x = null;
		if (this.degree == 0) {
			x = "";
		} else if (this.degree == 1) {
			x = "X";
		} else {
			x = "X^" + this.degree;
		}

		if (this.coef.isNull()) {
			return "0";
		} else if (this.coef.isOne()) {
			if (x.length() == 0) {
				return "1";
			} else {
				return x;
			}
		} else {
			if (x.length() != 0) {
				x = "*" + x;
			}
			return this.coef.toString() + x;
		}
	}

	/** Accesseur pour le coefficient du monôme. */
	public Rational getCoef() {
		return coef;
	}

	/** Accesseur pour le degré du monôme. */
	public int getDegree() {
		return degree;
	}
}
public class MonomialTest {
	public static void main(String[] args) {
		Monomial m = new Monomial(new Rational(3,4), 5);
		System.out.println(m);
	}
}
/**
 * Polynôme à coefficients rationnels.
 */
public class Polynomial {
	/** Tableau des monômes du polynôme. */
	private Monomial[] monomials;

	/** Initialise un polynôme à partir d'un tableau de monômes. */
	public Polynomial(Monomial[] monomials) {
		this.monomials = monomials;
	}

	/** Rend le degré du polynôme. */
	public int getDegree() {
		int deg = 0;
		for (Monomial m : this.monomials) {
			if (m.getDegree() > deg) {
				deg = m.getDegree();
			}
		}
		return deg;
	}

	/** Rend la valeur du polynôme pour une valeur de X */
	public Rational evaluate(Rational x) {
		Rational value = new Rational(0,1);
		for (Monomial m : this.monomials) {
			value = value.add(m.evaluate(x));
		}
		return value.simplify();
	}

	@Override
	public String toString() {
		// On utilise un StringBuffer pour construire la chaîne
		// car c'est plus efficace en termes d'allocation de mémoire.
		StringBuffer buf = new StringBuffer();
		// Traite-t-on le premier monôme ?
		boolean first = true;
		// Parcours des monômes du tableau
		for (Monomial m : this.monomials) {
			if (first) {
				// Si c'est le premier, ce ne le sera plus au tour suivant
				first = false;
			} else {
				// Si ce n'est pas le premier, le séparer du précédent par un "+"
				buf.append("+");
			}
			// Ajouter la représentation du monôme
			buf.append(m.toString());
		}
		// Rendre la chaîne construite.
		return buf.toString();
	}

	/** Autre version plus simple (et moins efficace) de toString. */
	public String toString2() {
		String buf = "";
		for (int i = 0; i < this.monomials.length; i++) {
			if (i > 0) {
				buf = buf + ("+");
			}
			buf = buf + this.monomials[i].toString();
		}
		return buf;
	}

}

Version avec la représentation qui utilise une TreeMap de monômes :

import java.util.TreeMap;

public class Polynomial2 {
	private TreeMap<Integer, Monomial> monomials;

	/** Initialise un polynôme à partir d'un tableau de monômes. */
	public Polynomial2(Monomial[] monomials) {
		// On crée la TreeMap 
		this.monomials = new TreeMap<Integer, Monomial>();
		// puis ajoute les monômes du tableau à notre polynôme.
		for (Monomial m : monomials) {
			this.add(m);
		}
	}

	/** Ajout d'un monôme au polynôme. */
	public void add(Monomial m) {
		// On mémorise le degré de m car on va l'utiliser souvent
		int deg = m.getDegree();

		if (this.monomials.containsKey(deg)) {
			// S'il y a déjà un monôme de même degré dans le polynôme
			Monomial d = this.monomials.get(deg);
			// on calcule son nouveau coefficient après l'jout du monôme
			Rational r = d.getCoef().add(m.getCoef()).simplify();
			if (r.isNull()) {
				// Si le nouveau coefficient est nul, on supprime le monôme
				this.monomials.remove(deg);
			} else {
				// Sinon, on le remplace par un monôme ayant le nouveau coefficient
				this.monomials.put(deg, new Monomial(r, deg));
			}
		} else {
			// S'il n'y avait pas de monôme de degré deg, on ajoute simplement le nouveau monôme
			this.monomials.put(deg, m);
		}
	}

	/** Ajout d'un polynôme à ce polynôme. */
	public void add(Polynomial2 p) {
		// Il suffit d'ajouter à ce polynôme chacun des monômes de p
		for (Monomial m : p.monomials.values()) {
			this.add(m);
		}
	}

	/** Rend le produit de ce polynôme par un polynôme. */
	public Polynomial2 multiply(Polynomial2 p) {
		// Le polynôme résultat ne contient initialement aucun monôme
		Polynomial2 result = new Polynomial2(new Monomial[] {});

		// On lui ajoute les produits deux à deux des monômes de ce polynôme et de p
		for (Monomial m: this.monomials.values()) {
			for (Monomial n : p.monomials.values()) {
				int deg = m.getDegree() + n.getDegree();
				Rational coeff = m.getCoef().multiply(n.getCoef()).simplify();
				result.add(new Monomial(coeff, deg));
			}
		}
		return result;
	}

	/** Rend le degré du polynôme. */
	public int getDegree() {
		// On utilise le fait qu'une TreeMap donne facilement sa clef 
		// la plus grande par la méthode lastKey()
		return this.monomials.lastKey();
	}

	/** Rend la valeur du polynôme pour une valeur de X */
	public Rational evaluate(Rational x) {
		// On part d'une valeur nulle
		Rational value = new Rational(0,1);
		// et on ajoute la valeur de chacun des monômes.
		// values() rend une collection contenant les valeurs associées 
		// aux clefs d'une TreeMap.
		for (Monomial m : this.monomials.values()) {
			value = value.add(m.evaluate(x));
		}
		return value.simplify();
	}

	@Override
	public String toString() {
		// On utilise un StringBuffer pour construire la chaîne
		// car c'est plus efficace en termes d'allocation de mémoire.
		StringBuffer buf = new StringBuffer();
		// Traite-t-on le premier monôme ?
		boolean first = true;
		// Parcours des monômes du tableau
		for (Monomial m : this.monomials.values()) {
			if (first) {
				// Si c'est le premier, ce ne le sera plus au tour suivant
				first = false;
			} else {
				// Si ce n'est pas le premier, le séparer du précédent par un "+"
				buf.append("+");
			}
			// Ajouter la représentation du monôme
			buf.append(m.toString());
		}
		// Rendre la chaîne construite.
		return buf.toString();
	}

}
public class PolynomialTest {
	public static void main(String[] args) {
		Monomial tab[] = new Monomial[3];
		tab[0] = new Monomial(new Rational(3,4), 5);
		tab[1] = new Monomial(new Rational(7,2), 2);
		tab[2] = new Monomial(new Rational(4,3), 0);
		Polynomial p = new Polynomial(tab);
		System.out.println(p);
		System.out.println(p.toString2());
		System.out.println(p.getDegree());
		System.out.println(p.evaluate(new Rational(2,5)));
		System.out.println(p.evaluate(new Rational(2,5)).approximate());

		Monomial tab2[] = {
				new Monomial(new Rational(1,1),1),
				new Monomial(new Rational(5,1),0),
				new Monomial(new Rational(1,1),0)
		};
		Polynomial pp = new Polynomial(tab2);
		System.out.println(pp);

		// Avec la deuxième représentation des polynomes (TreeMap)
		System.out.println("# TreeMap polynomials");
		Polynomial2 p2 = new Polynomial2(tab);
		System.out.println(p2);
		System.out.println(p2.getDegree());
		System.out.println(p2.evaluate(new Rational(2,5)));
		System.out.println(p2.evaluate(new Rational(2,5)).approximate());
		Polynomial2 pp2 = new Polynomial2(tab2);
		System.out.println(pp2);
		p2.add(new Monomial(new Rational(1,2),2));
		System.out.println(p2);
		p2.add(new Monomial(new Rational(-3,4),5));
		System.out.println(p2);
		System.out.println(p2.multiply(pp2));
	}
}

Deuxième BE (TDs 4 et 5)

Les résultats présentés ici ont été obtenus avec le modeleur UML Papyrus. Certaines déclarations ont été éditées à la main dans le code Java car la génération de code avec Papyrus n'est pas aussi paramétrable qu'avec RSA.

import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;

// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * A class for representing programs with variables and assignments.
 */
public class Program {
	/**
	 * A map for retrieving variables by their name.
	 */
	private Map<String, Variable> variables;

	/**
	 * The list of assignments (order matters) 
	 */
	private List<Assignment> assignments;

	@Override
	public String toString() {
		// We use a StringBuffer to optimize memory allocation while 
		// building the String representation of the program.
		StringBuffer buf = new StringBuffer();
		// This is the special sequence of characters that makes a new line
		String newline = System.getProperty("line.separator");
		// We display a program as its sequence of assignments 
		for (Assignment a : assignments) {
			buf.append(a.toString());
			buf.append(newline);
		}
		return buf.toString();
	}

	/**
	 * Get the variable named "n", create it if it does not exist.
	 * @param n the name of the variable
	 * @return the variable
	 */
	public Variable getVariable(String n) {
		if (! variables.containsKey(n)) {
			// If the variable is not in the map, create a new variable
			variables.put(n, new Variable(n,0));
		}
		// Return the variable associated to the key "n"
		return variables.get(n);
	}

	/**
	 * Add an assignment to the program
	 * @param v the variable to be assigned
	 * @param e the expression to assign to the variable
	 */
	public void addAssignment(Variable v, Expression e) {
		assignments.add(new Assignment(v, e));
	}

	/**
	 * Run a program: execute its assignments in sequence and display the final value of the variables.
	 */
	public void run() {
		// Firstly, execute the assignments in order (they are in a list)
		for (Assignment a : assignments) {
			a.execute();
		}
		// Secondly, print the value of the variables
		for (Variable v : variables.values()) {
			System.out.println(v + " : " + v.getValue());
		}
	}

	/**
	 * Initialize a new empty Program
	 */
	public Program() {
		this.variables = new HashMap<String, Variable>();
		this.assignments = new LinkedList<Assignment>();
	}

	/**
	 * Main function for testing our classes.
	 */
	public static void main(String args[]) {
		Program p = new Program();

		// getVariable() crée la variable si elle n'existe pas encore.
		p.addAssignment(p.getVariable("x"), new Number(2));
		p.addAssignment(p.getVariable("y"), new Plus(p.getVariable("x"), new Number(5)));
		p.addAssignment(p.getVariable("z"),
				new Divide(new Multiply(p.getVariable("x"), p.getVariable("x")), p.getVariable("y")));
		p.addAssignment(p.getVariable("x"), new Minus(p.getVariable("x"), new Number(1)));

		// Affiche les instructions
		System.out.println(p.toString());
		// Une ligne blanche
		System.out.println();

		// Exécute chaque instruction l'une après l'autre, puis affiche les variables et
		// leurs valeurs
		p.run();
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * A class for representing the assignment of an expression to a variable.
 */
public class Assignment {
	/**
	 * The assigned variable.
	 */
	private Variable variable;

	/**
	 * The expression to assign to the variable.
	 */
	private Expression expression;

	@Override
	public String toString() {
		return variable + " = " + expression;
	}

	/**
	 * Execute the assignment by assigning the current value of the expression to the variable. 
	 */
	public void execute() {
		variable.setValue(expression.getValue());
	}

	/**
	 * Initialize a new assignment.
	 * @param v the variable to set
	 * @param e the expression to assign to the variable
	 */
	public Assignment(Variable v, Expression e) {
		this.variable = v;
		this.expression = e;
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * Numbers are constant expressions.
 */
public class Number extends Expression {
	/**
	 * The value of the constant.
	 */
	private double value;

	/**
	 * Get the current value of the operator.
	 */
	@Override
	public double getValue() {
		return value;
	}

	@Override
	public String toString() {
		return Double.toString(value);
	}

	/**
	 * Initialize a Number from its value.
	 * @param val
	 */
	public Number(double val) {
		this.value = val;
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * Variables are named and hold a value that can be set.
 */
public class Variable extends Expression {
	/**
	 * The current value of the variable.
	 */
	private double value;

	/**
	 * The name of the variable.
	 */
	private String name;

	@Override
	public String toString() {
		return name;
	}

	/**
	 * Get the current value of the variable.
	 */
	@Override
	public double getValue() {
		return value;
	}

	/**
	 * Set the current value of the variable.
	 * @param v the new value.
	 */
	public void setValue(double v) {
		this.value = v;
	}

	/**
	 * Initialize a new Variable
	 * @param n the name of the variable
	 * @param v the initial value of the variable
	 */
	public Variable(String n, double v) {
		this.name = n;
		this.value = v;
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * A class for representing expressions that yield a double value.
 */
public abstract class Expression {
	/**
	 * Get the current value of the expression.
	 */
	public abstract double getValue();

	@Override
	public abstract String toString();
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * Binary operators as expressions.
 */
public abstract class BinaryOp extends Expression {
	/**
	 * Left operand of the binary operator.
	 */
	protected Expression leftOp;
	/**
	 * Right operand of the binary operator
	 */
	protected Expression rightOp;

	/**
	 * Initialize an binary operator from its operands.
	 * @param left  the left operand
	 * @param right the right operand
	 */
	public BinaryOp(Expression left, Expression right) {
		this.leftOp = left;
		this.rightOp = right;
	}

	/**
	 * Give the symbol of the binary operator (to be overridden by subclasses).
	 */
	public abstract String getOperator();

	@Override
	public String toString() {
		return "( " + leftOp + " " + getOperator() + " " + rightOp + " )";
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * The "add" binary operator.
 */
public class Plus extends BinaryOp {
	/**
	 * Get the current value of the operator.
	 */
	@Override
	public double getValue() {
		return leftOp.getValue() + rightOp.getValue();
	}

	/**
	 * Initialize a new Plus from its operands.
	 * @param left the left operand
	 * @param right the right operand
	 */
	public Plus(Expression left, Expression right) {
		// Just pass the arguments to the constructor of the super class
		super(left, right);
	}

	@Override
	public String getOperator() {
		return "+";
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * The "subtract" binary operator.
 */
public class Minus extends BinaryOp {
	/**
	 * Get the current value of the operator.
	 */
	@Override
	public double getValue() {
		return leftOp.getValue() - rightOp.getValue();
	}

	/**
	 * Initialize a new Minus from its operands.
	 * @param left the left operand
	 * @param right the right operand
	 */
	public Minus(Expression left, Expression right) {
		// Just pass the arguments to the constructor of the super class
		super(left, right);
	}

	/**
	 * 
	 * @return
	 */
	@Override
	public String getOperator() {
		return "-";
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * The "multiply" binary operator.
 */
public class Multiply extends BinaryOp {
	/**
	 * Get the current value of the operator.
	 */
	@Override
	public double getValue() {
		return leftOp.getValue() * rightOp.getValue();
	}

	/**
	 * Initialize a new Multiply from its operands.
	 * @param left the left operand
	 * @param right the right operand
	 */
	public Multiply(Expression left, Expression right) {
		// Just pass the arguments to the constructor of the super class
		super(left, right);
	}

	@Override
	public String getOperator() {
		return "*";
	}
};
// --------------------------------------------------------
// Code generated by Papyrus Java
// --------------------------------------------------------

/************************************************************/
/**
 * The "divide" binary operator.
 */
public class Divide extends BinaryOp {
	/**
	 * Get the current value of the operator.
	 */
	@Override
	public double getValue() {
		return leftOp.getValue() / rightOp.getValue();
	}

	/**
	 * Initialize a new Divide from its operands.
	 * @param left the left operand
	 * @param right the right operand
	 */
	public Divide(Expression left, Expression right) {
		// Just pass the arguments to the constructor of the super class
		super(left, right);
	}

	@Override
	public String getOperator() {
		return "/";
	}
};