package de.unisiegen.tpml.core.smallstep ; import org.apache.log4j.Logger ; import de.unisiegen.tpml.core.AbstractProofRuleSet ; import de.unisiegen.tpml.core.Messages ; import de.unisiegen.tpml.core.ProofGuessException ; import de.unisiegen.tpml.core.ProofNode ; import de.unisiegen.tpml.core.ProofRule ; import de.unisiegen.tpml.core.ProofRuleException ; import de.unisiegen.tpml.core.ProofStep ; import de.unisiegen.tpml.core.expressions.Expression ; import de.unisiegen.tpml.core.interpreters.AbstractInterpreterProofModel ; import de.unisiegen.tpml.core.interpreters.AbstractInterpreterProofNode ; import de.unisiegen.tpml.core.latex.DefaultLatexCommand ; import de.unisiegen.tpml.core.latex.DefaultLatexInstruction ; import de.unisiegen.tpml.core.latex.LatexCommandList ; import de.unisiegen.tpml.core.latex.LatexInstructionList ; import de.unisiegen.tpml.core.latex.LatexPackage ; import de.unisiegen.tpml.core.latex.LatexPackageList ; import de.unisiegen.tpml.core.latex.LatexPrintable ; import de.unisiegen.tpml.core.latex.LatexString ; import de.unisiegen.tpml.core.latex.LatexStringBuilder ; import de.unisiegen.tpml.core.latex.LatexStringBuilderFactory ; import de.unisiegen.tpml.core.prettyprinter.PrettyPrintable ; import de.unisiegen.tpml.core.prettyprinter.PrettyString ; import de.unisiegen.tpml.core.prettyprinter.PrettyStringBuilder ; import de.unisiegen.tpml.core.prettyprinter.PrettyStringBuilderFactory ; /** * The heart of the small step interpreter. Smallstep rules are supplied via an * {@link de.unisiegen.tpml.core.smallstep.AbstractSmallStepProofRuleSet} that * is passed to the constructor. * * @author Benedikt Meurer * @author Christian Fehler * @version $Rev$ * @see de.unisiegen.tpml.core.interpreters.AbstractInterpreterProofModel * @see de.unisiegen.tpml.core.smallstep.SmallStepProofNode */ public final class SmallStepProofModel extends AbstractInterpreterProofModel { /** * The {@link Logger} for this class. * * @see Logger */ private static final Logger logger = Logger .getLogger ( SmallStepProofModel.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_SMALL_STEP_NEW_NODE , 0 , "\\\\[10mm]" ) ) ; //$NON-NLS-1$ commands.add ( new DefaultLatexCommand ( LATEX_SMALL_STEP_NEW_RULE , 0 , "\\\\" ) ) ; //$NON-NLS-1$ commands.add ( new DefaultLatexCommand ( LATEX_SMALL_STEP_RULES_COMPLETED , 0 , "&" ) ) ; //$NON-NLS-1$ commands .add ( new DefaultLatexCommand ( LATEX_SMALL_STEP_PROOF_MODEL , 1 , "\\begin{longtable}{p{3.5cm}@{}p{22cm}@{}}#1\\end{longtable}" , "model" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ commands.add ( new DefaultLatexCommand ( LATEX_SMALL_STEP_ARROW , 2 , "\\xrightarrow" + LATEX_LINE_BREAK_NEW_COMMAND + "[\\mbox{\\color{" //$NON-NLS-1$//$NON-NLS-2$ + LATEX_COLOR_RULE + "}{\\scriptsize{#2}}}]" //$NON-NLS-1$ + LATEX_LINE_BREAK_NEW_COMMAND + "{\\mbox{\\color{" //$NON-NLS-1$ + LATEX_COLOR_RULE + "}{\\scriptsize{#1}}}}" , "not axiom rules" , //$NON-NLS-1$ //$NON-NLS-2$ "axiom rules" ) ) ; //$NON-NLS-1$ return commands ; } /** * Returns a set of needed latex instructions for this latex printable object. * * @return A set of needed latex instructions for this latex printable object. */ public static LatexInstructionList getLatexInstructionsStatic ( ) { LatexInstructionList instructions = new LatexInstructionList ( ) ; instructions.add ( new DefaultLatexInstruction ( "\\newenvironment{smallsteprulearrow}" //$NON-NLS-1$ + "{\\begin{tabular}[t]{p{3.5cm}@{}}}{\\end{tabular}}" , //$NON-NLS-1$ "The environment of the small step rules with the arrow" ) ) ; //$NON-NLS-1$ instructions.add ( new DefaultLatexInstruction ( "\\newenvironment{smallsteprules}" //$NON-NLS-1$ + "{\\begin{tabular}{p{2.5cm}@{}}}{\\end{tabular}}" , //$NON-NLS-1$ "The environment of the small step rules" ) ) ; //$NON-NLS-1$ instructions.add ( new DefaultLatexInstruction ( "\\newenvironment{smallstepnode}" //$NON-NLS-1$ + "{\\begin{tabular}[b]{p{22cm}@{}}}{\\end{tabular}}" , //$NON-NLS-1$ "The environment of the small step nodes" ) ) ; //$NON-NLS-1$ return instructions ; } /** * Returns a set of needed latex packages for this latex printable object. * * @return A set of needed latex packages for this latex printable object. */ public static LatexPackageList getLatexPackagesStatic ( ) { LatexPackageList packages = new LatexPackageList ( ) ; packages.add ( LatexPackage.AMSMATH ) ; packages.add ( LatexPackage.COLOR ) ; packages.add ( LatexPackage.LONGTABLE ) ; return packages ; } /** * Allocates a new <code>SmallStepProofModel</code> with the specified * <code>expression</code> as its root node. * * @param expression the {@link Expression} for the root node. * @param pRuleSet the available small step proof rules for the model. * @throws NullPointerException if either <code>expression</code> or * <code>ruleSet</code> is <code>null</code>. * @see AbstractInterpreterProofModel#AbstractInterpreterProofModel(AbstractInterpreterProofNode, * AbstractProofRuleSet) */ public SmallStepProofModel ( Expression expression , AbstractSmallStepProofRuleSet pRuleSet ) { super ( new DefaultSmallStepProofNode ( expression ) , pRuleSet ) ; // set the "finished" state initially setFinished ( expression.isException ( ) || expression.isValue ( ) ) ; } /** * {@inheritDoc} * * @see de.unisiegen.tpml.core.AbstractProofModel#addUndoableTreeEdit(de.unisiegen.tpml.core.AbstractProofModel.UndoableTreeEdit) */ @ Override protected void addUndoableTreeEdit ( UndoableTreeEdit edit ) { // perform the redo of the edit edit.redo ( ) ; // add to the undo history super.addUndoableTreeEdit ( edit ) ; } /** * Applies the <code>rule</code> to the <code>node</code>. The * <code>rule</code> must be any of the remaining rules for * <code>node</code>. * * @param rule the small step proof rule to apply to <code>node</code>. * @param node the node to which to apply the <code>rule</code>. * @throws ProofRuleException if the <code>rule</code> cannot be applied to * the <code>node</code>. * @see #apply(ProofRule, ProofNode) * @see #remaining(ProofNode) */ private void apply ( DefaultSmallStepProofRule rule , final DefaultSmallStepProofNode node ) throws ProofRuleException { // evaluate the expression and determine the proof steps DefaultSmallStepProofContext context = new DefaultSmallStepProofContext ( node , this.ruleSet ) ; final Expression expression = context.getExpression ( ) ; ProofStep [ ] evaluatedSteps = context.getSteps ( ) ; // determine the completed steps for the node final ProofStep [ ] completedSteps = node.getSteps ( ) ; // check if the node is already completed if ( completedSteps.length == evaluatedSteps.length ) { // check if the interpreter is stuck SmallStepProofRule lastRule = ( SmallStepProofRule ) evaluatedSteps [ evaluatedSteps.length - 1 ] .getRule ( ) ; if ( ! lastRule.isAxiom ( ) ) { // the proof is stuck throw new ProofRuleException ( node , rule ) ; } // an internal error in the upper layers throw new IllegalStateException ( "Cannot prove an already proven node" ) ; //$NON-NLS-1$ } else if ( completedSteps.length > evaluatedSteps.length ) { // this is a bug then throw new IllegalStateException ( "completedSteps > evaluatedSteps" ) ; //$NON-NLS-1$ } // verify the completed steps int n ; for ( n = 0 ; n < completedSteps.length ; ++ n ) { if ( ! completedSteps [ n ].getRule ( ).equals ( evaluatedSteps [ n ].getRule ( ) ) ) throw new IllegalStateException ( "Completed steps don't match evaluated steps" ) ; //$NON-NLS-1$ } // check if the rule is valid, accepting regular meta-rules for EXN rules int m ; for ( m = n ; m < evaluatedSteps.length ; ++ m ) { if ( evaluatedSteps [ m ].getRule ( ).equals ( rule ) || evaluatedSteps [ m ].getRule ( ).equals ( rule.toExnRule ( ) ) ) break ; } // check if rule is invalid if ( m >= evaluatedSteps.length ) { throw new ProofRuleException ( node , rule ) ; } // determine the new step(s) for the node final ProofStep [ ] newSteps = new ProofStep [ m + 1 ] ; System.arraycopy ( evaluatedSteps , 0 , newSteps , 0 , m + 1 ) ; // check if the node is finished (the last // step is an application of an axiom rule) if ( ( ( SmallStepProofRule ) newSteps [ m ].getRule ( ) ).isAxiom ( ) ) { // create the child node for the node final DefaultSmallStepProofNode child = new DefaultSmallStepProofNode ( expression , context.getStore ( ) ) ; // add the undoable edit addUndoableTreeEdit ( new UndoableTreeEdit ( ) { @ SuppressWarnings ( "synthetic-access" ) public void redo ( ) { // update the "finished" state setFinished ( expression.isException ( ) || expression.isValue ( ) ) ; // apply the new steps and add the child node.setSteps ( newSteps ) ; node.add ( child ) ; nodesWereInserted ( node , new int [ ] { node.getIndex ( child ) } ) ; nodeChanged ( node ) ; } @ SuppressWarnings ( "synthetic-access" ) public void undo ( ) { // update the "finished" state setFinished ( false ) ; // remove the child and revert the steps int [ ] indices = { node.getIndex ( child ) } ; node.remove ( child ) ; nodesWereRemoved ( node , indices , new Object [ ] { child } ) ; node.setSteps ( completedSteps ) ; nodeChanged ( node ) ; } } ) ; } else { // add the undoable edit addUndoableTreeEdit ( new UndoableTreeEdit ( ) { @ SuppressWarnings ( "synthetic-access" ) public void redo ( ) { // apply the new steps node.setSteps ( newSteps ) ; nodeChanged ( node ) ; } @ SuppressWarnings ( "synthetic-access" ) public void undo ( ) { // revert to the previous steps node.setSteps ( completedSteps ) ; nodeChanged ( node ) ; } } ) ; } } /** * Convenience wrapper for the * {@link #apply(DefaultSmallStepProofRule, DefaultSmallStepProofNode)} * method, which automatically casts to the appropriate types. * * @param rule the small step proof rule to apply to <code>node</code>. * @param node the node to which to apply the <code>rule</code>. * @throws ProofRuleException if the <code>rule</code> cannot be applied to * the <code>node</code>. * @see #apply(DefaultSmallStepProofRule, DefaultSmallStepProofNode) */ private void apply ( ProofRule rule , ProofNode node ) throws ProofRuleException { apply ( ( DefaultSmallStepProofRule ) rule , ( DefaultSmallStepProofNode ) node ) ; } /** * {@inheritDoc} * * @see LatexPrintable#getLatexCommands() */ public LatexCommandList getLatexCommands ( ) { LatexCommandList commands = new LatexCommandList ( ) ; commands.add ( getLatexCommandsStatic ( ) ) ; commands.add ( getLatexCommandsInternal ( this.root ) ) ; return commands ; } /** * Returns a set of needed latex commands for the given latex printable * {@link ProofNode}. * * @param pNode The input {@link ProofNode}. * @return A set of needed latex commands for the given latex printable * {@link ProofNode}. */ private LatexCommandList getLatexCommandsInternal ( ProofNode pNode ) { LatexCommandList commands = new LatexCommandList ( ) ; commands.add ( pNode ) ; commands.add ( pNode.getRules ( ) ) ; for ( int i = 0 ; i < pNode.getChildCount ( ) ; i ++ ) { commands.add ( getLatexCommandsInternal ( pNode.getChildAt ( i ) ) ) ; } return commands ; } /** * {@inheritDoc} * * @see LatexPrintable#getLatexInstructions() */ public LatexInstructionList getLatexInstructions ( ) { LatexInstructionList instructions = new LatexInstructionList ( ) ; instructions.add ( getLatexInstructionsStatic ( ) ) ; instructions.add ( getLatexInstructionsInternal ( this.root ) ) ; return instructions ; } /** * Returns a set of needed latex instructions for the given latex printable * {@link ProofNode}. * * @param pNode The input {@link ProofNode}. * @return A set of needed latex instructions for the given latex printable * {@link ProofNode}. */ private LatexInstructionList getLatexInstructionsInternal ( ProofNode pNode ) { LatexInstructionList instructions = new LatexInstructionList ( ) ; instructions.add ( pNode ) ; instructions.add ( pNode.getRules ( ) ) ; for ( int i = 0 ; i < pNode.getChildCount ( ) ; i ++ ) { instructions .add ( getLatexInstructionsInternal ( pNode.getChildAt ( i ) ) ) ; } return instructions ; } /** * {@inheritDoc} * * @see LatexPrintable#getLatexPackages() */ public LatexPackageList getLatexPackages ( ) { LatexPackageList packages = new LatexPackageList ( ) ; packages.add ( getLatexPackagesStatic ( ) ) ; packages.add ( getLatexPackagesInternal ( this.root ) ) ; return packages ; } /** * Returns a set of needed latex packages for the given latex printable * {@link ProofNode}. * * @param pNode The input {@link ProofNode}. * @return A set of needed latex packages for the given latex printable * {@link ProofNode}. */ private LatexPackageList getLatexPackagesInternal ( ProofNode pNode ) { LatexPackageList packages = new LatexPackageList ( ) ; packages.add ( pNode.getLatexPackages ( ) ) ; packages.add ( pNode.getRules ( ) ) ; for ( int i = 0 ; i < pNode.getChildCount ( ) ; i ++ ) { packages.add ( getLatexPackagesInternal ( pNode.getChildAt ( i ) ) ) ; } return packages ; } /** * {@inheritDoc} * * @see de.unisiegen.tpml.core.AbstractProofModel#guess(de.unisiegen.tpml.core.ProofNode) */ @ Override public void guess ( ProofNode node ) throws ProofGuessException { // guess the remaining steps for the node ProofStep [ ] remainingSteps = remaining ( node ) ; // check if the node is already completed if ( remainingSteps.length == 0 ) { // check if we are already completed if ( node.isProven ( ) ) { // the node is already proven, programming error throw new IllegalStateException ( "Cannot prove an already proven node" ) ; //$NON-NLS-1$ } // the evaluation got stuck throw new ProofGuessException ( Messages .getString ( "InterpreterModel.0" ) , node ) ; //$NON-NLS-1$ } // try to prove using the guessed rule try { // apply the last rule of the remaining steps to the node apply ( remainingSteps [ remainingSteps.length - 1 ].getRule ( ) , node ) ; // remember that the user cheated setCheating ( true ) ; } catch ( ProofRuleException e ) { // failed to guess throw new ProofGuessException ( node , e ) ; } } /** * {@inheritDoc} * * @see de.unisiegen.tpml.core.AbstractProofModel#prove(de.unisiegen.tpml.core.ProofRule, * de.unisiegen.tpml.core.ProofNode) */ @ Override public void prove ( ProofRule rule , ProofNode node ) throws ProofRuleException { if ( node == null ) { throw new NullPointerException ( "node is null" ) ; //$NON-NLS-1$ } if ( rule == null ) { throw new NullPointerException ( "rule is null" ) ; //$NON-NLS-1$ } if ( ! this.root.isNodeRelated ( node ) ) { throw new IllegalArgumentException ( "The node is invalid for the model" ) ; //$NON-NLS-1$ } if ( ! this.ruleSet.contains ( rule ) ) { throw new IllegalArgumentException ( "The rule is invalid for the model" ) ; //$NON-NLS-1$ } // apply the rule to the specified node try { apply ( rule , node ) ; } catch ( RuntimeException e ) { logger .error ( "An internal error occurred while proving " + node + " using (" + rule + ")" , e ) ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ throw e ; } } /** * Returns the remaining {@link de.unisiegen.tpml.core.ProofStep}s required * to prove the specified <code>node</code>. This method is used to guess * the next step, see the {@link #guess(ProofNode)} method for further * details, and in the user interface, to highlight the next expression. * * @param node the {@link de.unisiegen.tpml.core.ProofNode} for which to * return the remaining steps required to prove the <code>node</code>. * @return the remaining {@link ProofStep}s required to prove the * <code>node</code>, or an empty array if the <code>node</code> * is already proven or the evaluation is stuck. * @throws IllegalArgumentException if the <code>node</code> is invalid for * the model. * @throws NullPointerException if <code>node</code> is <code>null</code>. */ public ProofStep [ ] remaining ( ProofNode node ) { if ( node == null ) { throw new NullPointerException ( "node is null" ) ; //$NON-NLS-1$ } if ( ! this.root.isNodeRelated ( node ) ) { throw new IllegalArgumentException ( "The node is invalid for the model" ) ; //$NON-NLS-1$ } // evaluate the next step for the node DefaultSmallStepProofContext context = new DefaultSmallStepProofContext ( ( SmallStepProofNode ) node , this.ruleSet ) ; // determine the completed/evaluated steps ProofStep [ ] completedSteps = ( ( SmallStepProofNode ) node ).getSteps ( ) ; ProofStep [ ] evaluatedSteps = context.getSteps ( ) ; // generate the remaining steps ProofStep [ ] remainingSteps = new ProofStep [ evaluatedSteps.length - completedSteps.length ] ; System.arraycopy ( evaluatedSteps , completedSteps.length , remainingSteps , 0 , remainingSteps.length ) ; return remainingSteps ; } /** * {@inheritDoc} * * @see de.unisiegen.tpml.core.ProofModel#setOverlap(int) */ public void setOverlap ( @ SuppressWarnings ( "unused" ) int pOverlap ) { throw new UnsupportedOperationException ( ) ; } /** * {@inheritDoc} * * @see de.unisiegen.tpml.core.ProofModel#setPages(int) */ public void setPages ( @ SuppressWarnings ( "unused" ) int pPages ) { throw new UnsupportedOperationException ( ) ; } /** * {@inheritDoc} * * @see LatexPrintable#toLatexString() */ public final LatexString toLatexString ( ) { return toLatexStringBuilder ( LatexStringBuilderFactory.newInstance ( ) , 0 ) .toLatexString ( ) ; } /** * {@inheritDoc} * * @see LatexPrintable#toLatexStringBuilder(LatexStringBuilderFactory,int) */ public final LatexStringBuilder toLatexStringBuilder ( LatexStringBuilderFactory pLatexStringBuilderFactory , int pIndent ) { LatexStringBuilder builder = pLatexStringBuilderFactory.newBuilder ( 0 , LATEX_SMALL_STEP_PROOF_MODEL , pIndent , this.toPrettyString ( ) .toString ( ) ) ; builder.addBuilderBegin ( ) ; builder.addSourceCodeBreak ( 0 ) ; builder.addComment ( "no small step rules in the first node" ) ; //$NON-NLS-1$ builder.addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_RULES_COMPLETED ) ; builder.addSourceCodeBreak ( 0 ) ; // small steps builder.addText ( "\\begin{smallstepnode}" ) ; //$NON-NLS-1$ builder.addSourceCodeBreak ( 0 ) ; builder.addText ( "$" ) ; //$NON-NLS-1$ builder.addBuilderWithoutBrackets ( this.root.toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT ) , 0 ) ; builder.addSourceCodeBreak ( 0 ) ; builder.addText ( "$" ) ; //$NON-NLS-1$ builder.addSourceCodeBreak ( 0 ) ; builder.addText ( "\\end{smallstepnode}" ) ; //$NON-NLS-1$ if ( this.root.getChildCount ( ) > 0 ) { builder.addSourceCodeBreak ( 0 ) ; builder.addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_NEW_NODE ) ; builder.addSourceCodeBreak ( 0 ) ; } for ( int i = 0 ; i < this.root.getChildCount ( ) ; i ++ ) { toLatexStringBuilderInternal ( pLatexStringBuilderFactory , builder , this.root , this.root.getChildAt ( i ) , pIndent ) ; } builder.addBuilderEnd ( ) ; return builder ; } /** * Build the latex string for the given <code>pCurrentNode</code>. * * @param pLatexStringBuilderFactory The factory which should be used. * @param pLatexStringBuilder The {@link LatexStringBuilder} which should be * completed. * @param pParentNode The parent of the current {@link ProofNode}. This node * is needed because of his {@link ProofNode}s. * @param pCurrentNode The current {@link ProofNode}. * @param pIndent The indent of this object. */ public final void toLatexStringBuilderInternal ( LatexStringBuilderFactory pLatexStringBuilderFactory , LatexStringBuilder pLatexStringBuilder , ProofNode pParentNode , ProofNode pCurrentNode , int pIndent ) { ProofRule [ ] rules = pParentNode.getRules ( ) ; pLatexStringBuilder.addText ( "\\begin{smallsteprulearrow}" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder .addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_ARROW ) ; // not axiom rules pLatexStringBuilder.addBuilderBegin ( ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "\\begin{smallsteprules}" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ int countNotAxiomRules = 0 ; for ( int i = 0 ; i < rules.length ; i ++ ) { DefaultSmallStepProofRule rule = ( DefaultSmallStepProofRule ) rules [ i ] ; if ( ! rule.isAxiom ( ) ) { int sameRule = 1 ; for ( int j = i + 1 ; j < rules.length ; j ++ ) { if ( rules [ j ].getName ( ).equals ( rule.getName ( ) ) ) { sameRule ++ ; i = j ; } else { break ; } } if ( countNotAxiomRules > 0 ) { pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_NEW_RULE ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ } if ( sameRule > 1 ) { pLatexStringBuilder.addBuilder ( rule.toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT * 3 ) , 0 ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "^" + sameRule ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; } else { pLatexStringBuilder.addBuilder ( rule.toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT * 3 ) , 0 ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; } countNotAxiomRules ++ ; } } if ( countNotAxiomRules == 0 ) { pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; } pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "\\end{smallsteprules}" ) ;//$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addBuilderEnd ( ) ; // axiom rules pLatexStringBuilder.addBuilderBegin ( ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "\\begin{smallsteprules}" ) ;//$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ int countAxiomRules = 0 ; for ( int i = 0 ; i < rules.length ; i ++ ) { DefaultSmallStepProofRule rule = ( DefaultSmallStepProofRule ) rules [ i ] ; if ( rule.isAxiom ( ) ) { if ( countAxiomRules > 0 ) { pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_NEW_RULE ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ } pLatexStringBuilder.addBuilder ( rule.toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT * 3 ) , 0 ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; countAxiomRules ++ ; } } if ( countAxiomRules == 0 ) { pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; } pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "\\end{smallsteprules}" ) ;//$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addBuilderEnd ( ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "\\end{smallsteprulearrow}" ) ;//$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_RULES_COMPLETED ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; // small steps pLatexStringBuilder.addText ( "\\begin{smallstepnode}" ) ;//$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addBuilderWithoutBrackets ( pCurrentNode .toLatexStringBuilder ( pLatexStringBuilderFactory , pIndent + LATEX_INDENT ) , 0 ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "$" ) ; //$NON-NLS-1$ pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( "\\end{smallstepnode}" ) ;//$NON-NLS-1$ for ( int i = 0 ; i < pCurrentNode.getChildCount ( ) ; i ++ ) { pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; pLatexStringBuilder.addText ( LATEX_PREFIX_COMMAND + LATEX_SMALL_STEP_NEW_NODE ) ; pLatexStringBuilder.addSourceCodeBreak ( 0 ) ; toLatexStringBuilderInternal ( pLatexStringBuilderFactory , pLatexStringBuilder , pCurrentNode , pCurrentNode.getChildAt ( i ) , pIndent ) ; } } /** * {@inheritDoc} * * @see PrettyPrintable#toPrettyString() */ public final PrettyString toPrettyString ( ) { return toPrettyStringBuilder ( PrettyStringBuilderFactory.newInstance ( ) ) .toPrettyString ( ) ; } /** * {@inheritDoc} * * @see PrettyPrintable#toPrettyStringBuilder(PrettyStringBuilderFactory) */ public PrettyStringBuilder toPrettyStringBuilder ( PrettyStringBuilderFactory pPrettyStringBuilderFactory ) { PrettyStringBuilder builder = pPrettyStringBuilderFactory.newBuilder ( this , 0 ) ; builder.addBuilder ( this.root .toPrettyStringBuilder ( pPrettyStringBuilderFactory ) , 0 ) ; builder.addText ( PRETTY_LINE_BREAK ) ; builder.addText ( PRETTY_CONTINUATION ) ; return builder ; } /** * Returns the string representation for this model. This method is mainly * used for debugging. * * @return The pretty printed string representation for this model. * @see #toPrettyString() * @see Object#toString() */ @ Override public final String toString ( ) { return toPrettyString ( ).toString ( ) ; } }