package de.unisiegen.tpml.core.expressions ; import de.unisiegen.tpml.core.exceptions.NotOnlyFreeVariableException ; import de.unisiegen.tpml.core.interfaces.DefaultExpressions ; import de.unisiegen.tpml.core.latex.DefaultLatexCommand ; import de.unisiegen.tpml.core.latex.LatexCommandList ; import de.unisiegen.tpml.core.latex.LatexStringBuilder ; import de.unisiegen.tpml.core.latex.LatexStringBuilderFactory ; import de.unisiegen.tpml.core.prettyprinter.PrettyStringBuilder ; import de.unisiegen.tpml.core.prettyprinter.PrettyStringBuilderFactory ; import de.unisiegen.tpml.core.typechecker.TypeSubstitution ; /** * Represents the conditional evaluation in the expression hierarchy. The string * representation for conditions is <code>if e0 then e1 else e2</code>. * * @author Benedikt Meurer * @author Christian Fehler * @version $Rev:1053 $ * @see Expression */ public final class Condition extends Expression implements DefaultExpressions { /** * Indeces of the child {@link Expression}s. */ private static final int [ ] INDICES_E = new int [ ] { 0 , 1 , 2 } ; /** * String for the case that e0 is null. */ private static final String E0_NULL = "e0 is null" ; //$NON-NLS-1$ /** * String for the case that e1 is null. */ private static final String E1_NULL = "e1 is null" ; //$NON-NLS-1$ /** * String for the case that e2 is null. */ private static final String E2_NULL = "e2 is null" ; //$NON-NLS-1$ /** * The caption of this {@link Expression}. */ private static final String CAPTION = Expression .getCaption ( Condition.class ) ; /** * Returns a set of needed latex commands for this latex printable object. * * @return A set of needed latex commands for this latex printable object. */ public static LatexCommandList getLatexCommandsStatic ( ) { LatexCommandList commands = new LatexCommandList ( ) ; commands.add ( new DefaultLatexCommand ( LATEX_KEY_IF , 0 , "\\textbf{\\color{" + LATEX_COLOR_KEYWORD + "}{if}}" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ commands.add ( new DefaultLatexCommand ( LATEX_KEY_THEN , 0 , "\\textbf{\\color{" + LATEX_COLOR_KEYWORD + "}{then}}" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ commands.add ( new DefaultLatexCommand ( LATEX_KEY_ELSE , 0 , "\\textbf{\\color{" + LATEX_COLOR_KEYWORD + "}{else}}" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ commands.add ( new DefaultLatexCommand ( LATEX_CONDITION , 3 , "\\color{" //$NON-NLS-1$ + LATEX_COLOR_EXPRESSION + "}\\" + LATEX_KEY_IF + "\\ #1\\ \\" //$NON-NLS-1$ //$NON-NLS-2$ + LATEX_KEY_THEN + "\\ #2\\ \\" + LATEX_KEY_ELSE + "\\ #3" , "e0" , //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ "e1" , "e2" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ return commands ; } /** * The expressions. */ private Expression [ ] expressions ; /** * Allocates a new <code>Condition</code> with the specified <code>e0</code>, * <code>e1</code> and <code>e2</code>. * * @param pExpression0 the condition. * @param pExpression1 the <code>true</code> case. * @param pExpression2 the <code>false</code> case. * @throws NullPointerException if <code>e0</code>, <code>e1</code> or * <code>e2</code> is <code>null</code>. */ public Condition ( Expression pExpression0 , Expression pExpression1 , Expression pExpression2 ) { if ( pExpression0 == null ) { throw new NullPointerException ( E0_NULL ) ; } if ( pExpression1 == null ) { throw new NullPointerException ( E1_NULL ) ; } if ( pExpression2 == null ) { throw new NullPointerException ( E2_NULL ) ; } this.expressions = new Expression [ ] { pExpression0 , pExpression1 , pExpression2 } ; this.expressions [ 0 ].setParent ( this ) ; this.expressions [ 1 ].setParent ( this ) ; this.expressions [ 2 ].setParent ( this ) ; } /** * Allocates a new <code>Condition</code> with the specified <code>e0</code>, * <code>e1</code> and <code>e2</code>. * * @param pExpression0 the condition. * @param pExpression1 the <code>true</code> case. * @param pExpression2 the <code>false</code> case. * @param pParserStartOffset The start offset of this {@link Expression} in * the source code. * @param pParserEndOffset The end offset of this {@link Expression} in the * source code. * @throws NullPointerException if <code>e0</code>, <code>e1</code> or * <code>e2</code> is <code>null</code>. */ public Condition ( Expression pExpression0 , Expression pExpression1 , Expression pExpression2 , int pParserStartOffset , int pParserEndOffset ) { this ( pExpression0 , pExpression1 , pExpression2 ) ; this.parserStartOffset = pParserStartOffset ; this.parserEndOffset = pParserEndOffset ; } /** * {@inheritDoc} * * @see Expression#clone() */ @ Override public Condition clone ( ) { return new Condition ( this.expressions [ 0 ].clone ( ) , this.expressions [ 1 ].clone ( ) , this.expressions [ 2 ].clone ( ) ) ; } /** * {@inheritDoc} * * @see Expression#equals(Object) */ @ Override public boolean equals ( Object pObject ) { if ( pObject instanceof Condition ) { Condition other = ( Condition ) pObject ; return ( ( this.expressions [ 0 ].equals ( other.expressions [ 0 ] ) ) && ( this.expressions [ 1 ].equals ( other.expressions [ 1 ] ) ) && ( this.expressions [ 2 ] .equals ( other.expressions [ 2 ] ) ) ) ; } return false ; } /** * {@inheritDoc} */ @ Override public String getCaption ( ) { return CAPTION ; } /** * Returns the conditional expression. * * @return the conditional expression. */ public Expression getE0 ( ) { return this.expressions [ 0 ] ; } /** * Returns the expression that is evaluated if <code>e0</code> evaluates to * <code>true</code>. * * @return the <code>true</code> case. */ public Expression getE1 ( ) { return this.expressions [ 1 ] ; } /** * Returns the expression that is evaluated if <code>e0</code> evaluates to * <code>false</code>. * * @return the <code>false</code> case. */ public Expression getE2 ( ) { return this.expressions [ 2 ] ; } /** * Returns the sub expressions. * * @return the sub expressions. */ public Expression [ ] getExpressions ( ) { return this.expressions ; } /** * Returns the indices of the child {@link Expression}s. * * @return The indices of the child {@link Expression}s. */ public int [ ] getExpressionsIndex ( ) { return INDICES_E ; } /** * Returns a set of needed latex commands for this latex printable object. * * @return A set of needed latex commands for this latex printable object. */ @ Override public LatexCommandList getLatexCommands ( ) { LatexCommandList commands = super.getLatexCommands ( ) ; commands.add ( getLatexCommandsStatic ( ) ) ; return commands ; } /** * {@inheritDoc} * * @see Expression#hashCode() */ @ Override public int hashCode ( ) { return this.expressions [ 0 ].hashCode ( ) + this.expressions [ 1 ].hashCode ( ) + this.expressions [ 2 ].hashCode ( ) ; } /** * {@inheritDoc} * * @see Expression#substitute(Identifier, Expression) */ @ Override public Condition substitute ( Identifier pId , Expression pExpression ) { if ( pExpression.getIdentifierFreeNotOnlyVariable ( ) ) { throw new NotOnlyFreeVariableException ( ) ; } Expression newE0 = this.expressions [ 0 ].substitute ( pId , pExpression ) ; Expression newE1 = this.expressions [ 1 ].substitute ( pId , pExpression ) ; Expression newE2 = this.expressions [ 2 ].substitute ( pId , pExpression ) ; return new Condition ( newE0 , newE1 , newE2 ) ; } /** * {@inheritDoc} * * @see Expression#substitute(TypeSubstitution) */ @ Override public Condition substitute ( TypeSubstitution pTypeSubstitution ) { Expression newE0 = this.expressions [ 0 ].substitute ( pTypeSubstitution ) ; Expression newE1 = this.expressions [ 1 ].substitute ( pTypeSubstitution ) ; Expression newE2 = this.expressions [ 2 ].substitute ( pTypeSubstitution ) ; return new Condition ( newE0 , newE1 , newE2 ) ; } /** * {@inheritDoc} * * @see Expression#toLatexStringBuilder(LatexStringBuilderFactory,int) */ @ Override public LatexStringBuilder toLatexStringBuilder ( LatexStringBuilderFactory pLatexStringBuilderFactory , int pIndent ) { LatexStringBuilder builder = pLatexStringBuilderFactory.newBuilder ( PRIO_CONDITION , LATEX_CONDITION , pIndent , this.toPrettyString ( ) .toString ( ) , this.expressions [ 0 ].toPrettyString ( ) .toString ( ) , this.expressions [ 1 ].toPrettyString ( ) .toString ( ) , this.expressions [ 2 ].toPrettyString ( ) .toString ( ) ) ; builder.addBuilder ( this.expressions [ 0 ].toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT ) , PRIO_CONDITION_E0 ) ; builder.addBreak ( ) ; builder.addBuilder ( this.expressions [ 1 ].toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT ) , PRIO_CONDITION_E1 ) ; builder.addBreak ( ) ; builder.addBuilder ( this.expressions [ 2 ].toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT ) , PRIO_CONDITION_E2 ) ; return builder ; } /** * {@inheritDoc} * * @see Expression#toPrettyStringBuilder(PrettyStringBuilderFactory) */ @ Override public PrettyStringBuilder toPrettyStringBuilder ( PrettyStringBuilderFactory pPrettyStringBuilderFactory ) { if ( this.prettyStringBuilder == null ) { this.prettyStringBuilder = pPrettyStringBuilderFactory.newBuilder ( this , PRIO_CONDITION ) ; this.prettyStringBuilder.addKeyword ( PRETTY_IF ) ; this.prettyStringBuilder.addText ( PRETTY_SPACE ) ; this.prettyStringBuilder.addBuilder ( this.expressions [ 0 ] .toPrettyStringBuilder ( pPrettyStringBuilderFactory ) , PRIO_CONDITION_E0 ) ; this.prettyStringBuilder.addText ( PRETTY_SPACE ) ; this.prettyStringBuilder.addBreak ( ) ; this.prettyStringBuilder.addKeyword ( PRETTY_THEN ) ; this.prettyStringBuilder.addText ( PRETTY_SPACE ) ; this.prettyStringBuilder.addBuilder ( this.expressions [ 1 ] .toPrettyStringBuilder ( pPrettyStringBuilderFactory ) , PRIO_CONDITION_E1 ) ; this.prettyStringBuilder.addText ( PRETTY_SPACE ) ; this.prettyStringBuilder.addBreak ( ) ; this.prettyStringBuilder.addKeyword ( PRETTY_ELSE ) ; this.prettyStringBuilder.addText ( PRETTY_SPACE ) ; this.prettyStringBuilder.addBuilder ( this.expressions [ 2 ] .toPrettyStringBuilder ( pPrettyStringBuilderFactory ) , PRIO_CONDITION_E2 ) ; } return this.prettyStringBuilder ; } }