diff --git a/src/main/dig/sequential/Counter-D.dig b/src/main/dig/sequential/Counter-D.dig index 676f4b8f9..c0feb2f2b 100644 --- a/src/main/dig/sequential/Counter-D.dig +++ b/src/main/dig/sequential/Counter-D.dig @@ -1,6 +1,7 @@ 1 + Tunnel @@ -21,7 +22,7 @@ Label - q_3n + q_3^n Inputs @@ -29,7 +30,7 @@ Default - 1 + 1 @@ -88,7 +89,7 @@ Label - q_2n + q_2^n Inputs @@ -96,7 +97,7 @@ Default - 1 + 1 @@ -150,7 +151,7 @@ Label - q_1n + q_1^n Inputs @@ -158,7 +159,7 @@ Default - 1 + 1 @@ -197,7 +198,7 @@ Label - q_0n + q_0^n Inputs diff --git a/src/main/dig/sequential/Counter-JK.dig b/src/main/dig/sequential/Counter-JK.dig index 564fab155..cdcf12f0f 100644 --- a/src/main/dig/sequential/Counter-JK.dig +++ b/src/main/dig/sequential/Counter-JK.dig @@ -22,7 +22,7 @@ Label - q_0n + q_0^n @@ -32,7 +32,7 @@ Label - q_1n + q_1^n Default @@ -46,7 +46,7 @@ Label - q_2n + q_2^n Default @@ -60,7 +60,7 @@ Label - q_3n + q_3^n Default diff --git a/src/main/java/de/neemann/digital/analyse/DetermineJKStateMachine.java b/src/main/java/de/neemann/digital/analyse/DetermineJKStateMachine.java index d872482b1..354638717 100644 --- a/src/main/java/de/neemann/digital/analyse/DetermineJKStateMachine.java +++ b/src/main/java/de/neemann/digital/analyse/DetermineJKStateMachine.java @@ -6,8 +6,6 @@ package de.neemann.digital.analyse; import de.neemann.digital.analyse.expression.*; -import de.neemann.digital.analyse.expression.format.FormatToExpression; -import de.neemann.digital.analyse.expression.format.FormatterException; import de.neemann.digital.analyse.quinemc.QuineMcCluskey; import de.neemann.digital.lang.Lang; @@ -34,10 +32,10 @@ public class DetermineJKStateMachine { * @param name the name of the state variable * @param e the expression to split in J and K expression * @throws ExpressionException ExpressionException - * @throws FormatterException FormatterException */ - public DetermineJKStateMachine(String name, Expression e) throws ExpressionException, FormatterException { - String notName = FormatToExpression.defaultFormat(not(new Variable(name))); + public DetermineJKStateMachine(String name, Expression e) throws ExpressionException { + final Expression var = new Variable(name); + final Expression notVar = not(var); boolean wasK = false; boolean wasJ = false; @@ -48,11 +46,10 @@ public class DetermineJKStateMachine { boolean belongsToJ = false; for (Expression a : getAnds(or)) { - String str = FormatToExpression.defaultFormat(a); - if (str.equals(name)) { + if (a.equals(var)) { belongsToK = true; wasK = true; - } else if (str.equals(notName)) { + } else if (a.equals(notVar)) { belongsToJ = true; wasJ = true; } else { diff --git a/src/main/java/de/neemann/digital/analyse/LabelNumbering.java b/src/main/java/de/neemann/digital/analyse/LabelNumbering.java index 615e820a6..0918f8d69 100644 --- a/src/main/java/de/neemann/digital/analyse/LabelNumbering.java +++ b/src/main/java/de/neemann/digital/analyse/LabelNumbering.java @@ -12,6 +12,7 @@ public class LabelNumbering { private final String name; private int pos; + private boolean useIndex = false; /** * Creates a new instance @@ -21,9 +22,10 @@ public class LabelNumbering { public LabelNumbering(String name) { this.name = name; pos = name.length(); - if (name.endsWith("_n")) + if (name.endsWith("^n")) { pos = name.length() - 2; - else if (name.endsWith("n")) + useIndex = !name.contains("_"); + } else if (name.endsWith("n")) pos = name.length() - 1; } @@ -48,7 +50,10 @@ public class LabelNumbering { } private String addNumber(int n) { - return name.substring(0, pos) + n + name.substring(pos); + if (useIndex) + return name.substring(0, pos) + "_" + n + name.substring(pos); + else + return name.substring(0, pos) + n + name.substring(pos); } /** diff --git a/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java b/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java index 11c70b139..a37a94f8e 100644 --- a/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java +++ b/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java @@ -68,7 +68,7 @@ public class ModelAnalyser { ff.getDInput().removeObserver(ff); // turn off flipflop String label = getUniqueNameFor(ff); - outputs.add(i++, new Signal(label + "+1", ff.getDInput())); + outputs.add(i++, new Signal(addOne(label), ff.getDInput())); modelAnalyzerInfo.setSequentialInitValue(label, ff.getDefault()); @@ -93,13 +93,27 @@ public class ModelAnalyser { throw new AnalyseException(Lang.get("err_analyseNoOutputs")); } + /** + * Adds the "+1" to the variables name + * + * @param name the vars name + * @return the modified name + */ + public static String addOne(String name) { + if (name.endsWith("^n")) + return name.substring(0, name.length() - 1) + "{n+1}"; + else + return name + "+1"; + } + + private String getUniqueNameFor(FlipflopD ff) { String label = ff.getLabel(); if (label.length() == 0) label = createOutputBasedName(ff); if (!label.endsWith("n")) - label += "n"; + label += "^n"; return new LabelNumbering(label).create(this::inputExist); } @@ -231,11 +245,13 @@ public class ModelAnalyser { String label = ff.getLabel(); if (label.length() == 0) label = createOutputBasedName(ff); + if (!label.contains("_")) + label = label + "_"; long def = ff.getDefault(); for (int i = ff.getDataBits() - 1; i >= 0; i--) { ObservableValue qn = new ObservableValue("", 1); ObservableValue nqn = new ObservableValue("", 1); - FlipflopD newff = new FlipflopD(label + i, qn, nqn, (def & (1L< expressions, String opString) throws FormatterException { - StringBuilder sb = new StringBuilder(); - for (Expression e : expressions) { - if (sb.length() > 0) { - sb.append(" "); - if (opString.length() > 0) - sb.append(opString).append(" "); - } - if (e instanceof Operation) - sb.append("(").append(format(e)).append(")"); - else - sb.append(format(e)); - } - return sb.toString(); + public String getNot() { + return notString; + } + + /** + * @return the EQUAL string + */ + public String getEqual() { + if (equal == null) // compatibility with old config files!!! + return "="; + return equal; } /** @@ -250,23 +188,14 @@ public class FormatToExpression implements Formatter { else return falseString; } - /** - * Formats the given identifier - * - * @param identifier the identifier - * @return the string representation of the identifier - */ - public String identifier(String identifier) { - return identifier; + @Override + public String format(Expression expression) { + return PlainTextFormatter.format(new ExpressionToText().setFormatIdentifiers(!keepVars).createText(expression, this), this); } @Override public String toString() { - try { - return format(TOSTRING_EXPR); - } catch (FormatterException e1) { - return "format error"; - } + return format(TOSTRING_EXPR); } @Override @@ -279,7 +208,8 @@ public class FormatToExpression implements Formatter { && Objects.equals(falseString, that.falseString) && Objects.equals(trueString, that.trueString) && Objects.equals(xorString, that.xorString) - && Objects.equals(notString, that.notString); + && Objects.equals(notString, that.notString) + && Objects.equals(equal, that.equal); } @Override @@ -287,19 +217,4 @@ public class FormatToExpression implements Formatter { return Objects.hash(orString, andString, falseString, trueString, xorString, notString); } - private static class FormatterLatex extends FormatToExpression { - FormatterLatex() { - super("\\oder", "\\und", "\\xoder", null, "0", "1"); - } - - @Override - public String formatNot(Not expression) throws FormatterException { - return "\\nicht{" + format(expression.getExpression()) + "}"; - } - - @Override - public String identifier(String identifier) { - return FormatToTableLatex.formatIdentifier(identifier); - } - } } diff --git a/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTable.java b/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTable.java index defd46b28..36f0797c5 100644 --- a/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTable.java +++ b/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTable.java @@ -17,7 +17,7 @@ import de.neemann.digital.analyse.expression.Variable; public class FormatToTable implements Formatter { @Override - public String format(Expression expression) throws FormatterException, ExpressionException { + public String format(Expression expression) throws ExpressionException { StringBuilder sb = new StringBuilder(); ContextFiller cf = new ContextFiller(expression); formatHead(sb, cf.getVarCount()); diff --git a/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java b/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java index a353700b3..f90e50acf 100644 --- a/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java +++ b/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java @@ -7,6 +7,7 @@ package de.neemann.digital.analyse.expression.format; import de.neemann.digital.analyse.expression.Variable; +import de.neemann.digital.draw.graphics.text.formatter.LaTeXFormatter; /** */ @@ -22,7 +23,7 @@ public class FormatToTableLatex extends FormatToTable { @Override protected String formatVariable(Variable v) { - return "$" + formatIdentifier(super.formatVariable(v)) + "$&"; + return "$" + LaTeXFormatter.format(v) + "$&"; } @Override @@ -50,17 +51,4 @@ public class FormatToTableLatex extends FormatToTable { sb.append("\\end{tabular}\n"); } - /** - * Formats the given identifier - * - * @param identifier the identifier - * @return the formatted text - */ - public static String formatIdentifier(String identifier) { - int p = identifier.indexOf("^"); - if (p < 0) return identifier; - - String index = identifier.substring(p + 1); - return identifier.substring(0, p + 1) + "{" + index + "}"; - } } diff --git a/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java index cccde8a3f..d36082012 100644 --- a/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java +++ b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java @@ -9,8 +9,8 @@ import de.neemann.digital.analyse.TruthTable; import de.neemann.digital.analyse.expression.ContextFiller; import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.Variable; -import de.neemann.digital.analyse.expression.format.FormatToTableLatex; import de.neemann.digital.analyse.quinemc.ThreeStateValue; +import de.neemann.digital.draw.graphics.text.formatter.LaTeXFormatter; /** */ @@ -27,9 +27,9 @@ public class TruthTableFormatterLaTeX implements TruthTableFormatter { sb.append("}\n"); for (Variable v : truthTable.getVars()) - sb.append("$").append(formatVar(v.getIdentifier())).append("$&"); + sb.append("$").append(LaTeXFormatter.format(v)).append("$&"); for (int i = 0; i < truthTable.getResultCount(); i++) { - sb.append("$").append(formatVar(truthTable.getResultName(i))).append("$"); + sb.append("$").append(LaTeXFormatter.format(new Variable(truthTable.getResultName(i)))).append("$"); if (i < truthTable.getResultCount() - 1) sb.append("&"); } @@ -70,7 +70,4 @@ public class TruthTableFormatterLaTeX implements TruthTableFormatter { return null; } - private static String formatVar(String var) { - return FormatToTableLatex.formatIdentifier(var); - } } diff --git a/src/main/java/de/neemann/digital/builder/Gal16v8/CuplExporter.java b/src/main/java/de/neemann/digital/builder/Gal16v8/CuplExporter.java index b526aba09..5a6ca8bc4 100644 --- a/src/main/java/de/neemann/digital/builder/Gal16v8/CuplExporter.java +++ b/src/main/java/de/neemann/digital/builder/Gal16v8/CuplExporter.java @@ -9,7 +9,6 @@ import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.ExpressionVisitor; import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.expression.format.FormatToExpression; -import de.neemann.digital.analyse.expression.format.FormatterException; import de.neemann.digital.builder.*; import de.neemann.digital.builder.jedec.FuseMapFillerException; import de.neemann.digital.lang.Lang; @@ -127,8 +126,8 @@ public class CuplExporter implements ExpressionExporter { * Writes code to given writer * * @param out the stream to write to - * @throws IOException IOException - * @throws PinMapException PinMapException + * @throws IOException IOException + * @throws PinMapException PinMapException */ public void writeTo(Writer out) throws IOException, PinMapException { out @@ -166,27 +165,23 @@ public class CuplExporter implements ExpressionExporter { } } - try { - if (!builder.getRegistered().isEmpty()) { - out.append("\r\n/* sequential logic */\r\n"); - for (Map.Entry c : builder.getRegistered().entrySet()) { - out.append(c.getKey()).append(".D = "); - breakLines(out, FormatToExpression.FORMATTER_CUPL.format(c.getValue())); - out.append(";\r\n"); - sequentialWritten(out, c.getKey()); - } + if (!builder.getRegistered().isEmpty()) { + out.append("\r\n/* sequential logic */\r\n"); + for (Map.Entry c : builder.getRegistered().entrySet()) { + out.append(c.getKey()).append(".D = "); + breakLines(out, FormatToExpression.FORMATTER_CUPL.format(c.getValue())); + out.append(";\r\n"); + sequentialWritten(out, c.getKey()); } + } - if (!builder.getCombinatorial().isEmpty()) { - out.append("\r\n/* combinatorial logic */\r\n"); - for (Map.Entry c : builder.getCombinatorial().entrySet()) { - out.append(c.getKey()).append(" = "); - breakLines(out, FormatToExpression.FORMATTER_CUPL.format(c.getValue())); - out.append(";\r\n"); - } + if (!builder.getCombinatorial().isEmpty()) { + out.append("\r\n/* combinatorial logic */\r\n"); + for (Map.Entry c : builder.getCombinatorial().entrySet()) { + out.append(c.getKey()).append(" = "); + breakLines(out, FormatToExpression.FORMATTER_CUPL.format(c.getValue())); + out.append(";\r\n"); } - } catch (FormatterException e) { - throw new IOException(e); } out.flush(); diff --git a/src/main/java/de/neemann/digital/builder/circuit/CircuitBuilder.java b/src/main/java/de/neemann/digital/builder/circuit/CircuitBuilder.java index b57ce9716..e6dffbe42 100644 --- a/src/main/java/de/neemann/digital/builder/circuit/CircuitBuilder.java +++ b/src/main/java/de/neemann/digital/builder/circuit/CircuitBuilder.java @@ -9,7 +9,6 @@ import de.neemann.digital.analyse.DetermineJKStateMachine; import de.neemann.digital.analyse.ModelAnalyserInfo; import de.neemann.digital.analyse.expression.*; import de.neemann.digital.analyse.expression.Not; -import de.neemann.digital.analyse.expression.format.FormatterException; import de.neemann.digital.builder.BuilderException; import de.neemann.digital.builder.BuilderInterface; import de.neemann.digital.core.basic.*; @@ -182,7 +181,7 @@ public class CircuitBuilder implements BuilderInterface { fragments.add(new FragmentExpression(Arrays.asList(frJ, frK), fe)); } } - } catch (ExpressionException | FormatterException e) { + } catch (ExpressionException e) { throw new BuilderException(e.getMessage()); } } diff --git a/src/main/java/de/neemann/digital/draw/graphics/text/formatter/GraphicsFormatter.java b/src/main/java/de/neemann/digital/draw/graphics/text/formatter/GraphicsFormatter.java index d863d3e40..0263d6826 100644 --- a/src/main/java/de/neemann/digital/draw/graphics/text/formatter/GraphicsFormatter.java +++ b/src/main/java/de/neemann/digital/draw/graphics/text/formatter/GraphicsFormatter.java @@ -5,12 +5,12 @@ */ package de.neemann.digital.draw.graphics.text.formatter; -import de.neemann.digital.analyse.expression.*; -import de.neemann.digital.analyse.expression.format.FormatToExpression; +import de.neemann.digital.analyse.expression.Expression; +import de.neemann.digital.draw.graphics.text.text.ExpressionToText; import de.neemann.digital.draw.graphics.text.ParseException; import de.neemann.digital.draw.graphics.text.Parser; -import de.neemann.digital.draw.graphics.text.text.*; import de.neemann.digital.draw.graphics.text.text.Character; +import de.neemann.digital.draw.graphics.text.text.*; import java.awt.*; import java.awt.geom.Rectangle2D; @@ -21,8 +21,6 @@ import java.util.ArrayList; */ public final class GraphicsFormatter { - private static final FormatToExpression DEFAULT_FORMAT = FormatToExpression.getDefaultFormat(); - private GraphicsFormatter() { } @@ -41,6 +39,22 @@ public final class GraphicsFormatter { }, gr.getFont(), text); } + /** + * Creates the text fragments + * + * @param gr the {@link Graphics2D} instance + * @param expression the expression + * @return the text fragment + * @throws FormatterException FormatterException + */ + public static Fragment createFragment(Graphics2D gr, Expression expression) throws FormatterException { + return createFragment((fragment, font, str) -> { + final FontMetrics metrics = gr.getFontMetrics(font); + Rectangle2D rec = metrics.getStringBounds(str, gr); + fragment.set((int) rec.getWidth(), (int) rec.getHeight(), metrics.getDescent()); + }, gr.getFont(), new ExpressionToText().createText(expression)); + } + /** * Creates the text fragments * @@ -107,81 +121,6 @@ public final class GraphicsFormatter { throw new FormatterException("unknown text element " + text.getClass().getSimpleName() + ", " + text); } - /** - * Creates the text fragments - * - * @param gr the {@link Graphics2D} instance - * @param expression the expression - * @return the text fragment - * @throws FormatterException FormatterException - */ - public static Fragment createFragment(Graphics2D gr, Expression expression) throws FormatterException { - return createFragment((fragment, font, str) -> { - final FontMetrics metrics = gr.getFontMetrics(font); - Rectangle2D rec = metrics.getStringBounds(str, gr); - fragment.set((int) rec.getWidth(), (int) rec.getHeight(), metrics.getDescent()); - }, gr.getFont(), expression); - } - - /** - * Creates the text fragments - * - * @param sizer the sizer instance - * @param font the font - * @param expression the expression - * @return the fragment - * @throws FormatterException FormatterException - */ - public static Fragment createFragment(FontSizer sizer, Font font, Expression expression) throws FormatterException { - if (expression instanceof Variable) { - String ident = ((Variable) expression).getIdentifier(); - return createFragment(sizer, font, ident); - } else if (expression instanceof Constant) { - String value = DEFAULT_FORMAT.constant(((Constant) expression).getValue()); - return new TextFragment(sizer, font, value); - } else if (expression instanceof Operation.And) { - return createOperationFragment(sizer, font, (Operation) expression, DEFAULT_FORMAT.getAndString()); - } else if (expression instanceof Operation.Or) { - return createOperationFragment(sizer, font, (Operation) expression, DEFAULT_FORMAT.getOrString()); - } else if (expression instanceof Operation.XOr) { - return createOperationFragment(sizer, font, (Operation) expression, DEFAULT_FORMAT.getXorString()); - } else if (expression instanceof Not) { - return new OverlineFragment(createFragment(sizer, font, ((Not) expression).getExpression()), font); - } else if (expression instanceof NamedExpression) { - NamedExpression ne = (NamedExpression) expression; - SentenceFragment f = new SentenceFragment(); - f.add(createFragment(sizer, font, ne.getName())); - f.pad(font.getSize() / 2); - f.add(new TextFragment(sizer, font, "=")); - f.pad(font.getSize() / 2); - f.add(createFragment(sizer, font, ne.getExpression())); - return f.setUp(); - } else - throw new FormatterException("unknown expression " + expression.getClass().getSimpleName()); - } - - private static Fragment createOperationFragment(FontSizer sizer, Font font, Operation op, String opString) throws FormatterException { - int pad = font.getSize() / 2; - SentenceFragment f = new SentenceFragment(); - for (Expression e : op.getExpressions()) { - if (f.size() > 0) { - f.pad(pad); - if (!opString.isEmpty()) { - f.add(new TextFragment(sizer, font, opString)); - f.pad(pad); - } - } - if (e instanceof Operation) { - f.add(new TextFragment(sizer, font, "(")); - f.add(createFragment(sizer, font, e)); - f.add(new TextFragment(sizer, font, ")")); - } else { - f.add(createFragment(sizer, font, e)); - } - } - return f.setUp(); - } - /** * Exception which indicates a formatter exception */ @@ -311,10 +250,6 @@ public final class GraphicsFormatter { base = maxBase; return this; } - - private int size() { - return fragments.size(); - } } private final static class IndexFragment extends Fragment { diff --git a/src/main/java/de/neemann/digital/draw/graphics/text/formatter/LaTeXFormatter.java b/src/main/java/de/neemann/digital/draw/graphics/text/formatter/LaTeXFormatter.java index b6e02822f..d5e06174c 100644 --- a/src/main/java/de/neemann/digital/draw/graphics/text/formatter/LaTeXFormatter.java +++ b/src/main/java/de/neemann/digital/draw/graphics/text/formatter/LaTeXFormatter.java @@ -5,6 +5,8 @@ */ package de.neemann.digital.draw.graphics.text.formatter; +import de.neemann.digital.analyse.expression.Expression; +import de.neemann.digital.analyse.expression.format.FormatToExpression; import de.neemann.digital.draw.graphics.text.text.*; import de.neemann.digital.draw.graphics.text.text.Character; @@ -16,6 +18,15 @@ public final class LaTeXFormatter { private LaTeXFormatter() { } + /** + * Formats the given text + * + * @param exp the expression to format + * @return the formatted string + */ + public static String format(Expression exp) { + return format(new ExpressionToText().createText(exp, FormatToExpression.FORMATTER_LATEX), true); + } /** * Formats the given text * @@ -49,7 +60,7 @@ public final class LaTeXFormatter { if (c instanceof Index) return "$\\overline{" + format(c, true) + "}$"; else - return "$\\overline{\\mbox{" + format(c, false) + "}}$"; + return "$\\overline{\\mbox{" + format(c, true) + "}}$"; } default: return format(d.getContent(), mathMode); diff --git a/src/main/java/de/neemann/digital/draw/graphics/text/formatter/PlainTextFormatter.java b/src/main/java/de/neemann/digital/draw/graphics/text/formatter/PlainTextFormatter.java new file mode 100644 index 000000000..adcb77bc5 --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/graphics/text/formatter/PlainTextFormatter.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.draw.graphics.text.formatter; + +import de.neemann.digital.analyse.expression.format.FormatToExpression; +import de.neemann.digital.draw.graphics.text.text.*; +import de.neemann.digital.draw.graphics.text.text.Character; + +/** + * Is used to create a simple string + */ +public final class PlainTextFormatter { + + private PlainTextFormatter() { + } + + /** + * Creates a simple string + * + * @param text the text + * @return the string representation + */ + public static String format(Text text) { + return format(text, FormatToExpression.getDefaultFormat()); + } + + /** + * Creates a simple string + * + * @param text the text + * @param format the format to use + * @return the string representation + */ + public static String format(Text text, FormatToExpression format) { + if (text instanceof Simple) { + return ((Simple) text).getText(); + } else if (text instanceof Blank) { + return " "; + } else if (text instanceof Character) { + return "" + ((Character) text).getChar(); + } else if (text instanceof Decorate) { + Decorate d = (Decorate) text; + if (d.getStyle() == Decorate.Style.OVERLINE) { + final Text content = d.getContent(); + if (content instanceof Simple || content instanceof Index) + return format.getNot() + format(content, format); + else + return format.getNot() + "(" + format(content, format) + ")"; + } else + return format(d.getContent(), format); + } else if (text instanceof Index) { + Index i = (Index) text; + String str = format(i.getVar(), format); + if (i.getSubScript() != null) + str += format(i.getSubScript(), format); + if (i.getSuperScript() != null) + str += format(i.getSuperScript(), format); + return str; + } else if (text instanceof Sentence) { + Sentence s = (Sentence) text; + StringBuilder sb = new StringBuilder(); + for (Text t : s) + sb.append(format(t, format)); + return sb.toString(); + } else return ""; + } + +} diff --git a/src/main/java/de/neemann/digital/draw/graphics/text/text/ExpressionToText.java b/src/main/java/de/neemann/digital/draw/graphics/text/text/ExpressionToText.java new file mode 100644 index 000000000..e33c04bf0 --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/graphics/text/text/ExpressionToText.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2019 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.draw.graphics.text.text; + +import de.neemann.digital.analyse.expression.*; +import de.neemann.digital.analyse.expression.format.FormatToExpression; +import de.neemann.digital.draw.graphics.text.ParseException; +import de.neemann.digital.draw.graphics.text.Parser; + +/** + * Used to create a text structure from an expression. + */ +public class ExpressionToText { + + private boolean formatIdentifiers = true; + + /** + * Creates a new instance + */ + public ExpressionToText() { + } + + /** + * If set to false, the identifiers are unchanged + * + * @param formatIdetifiers set to false to keep identifiers unchanged + * @return this for chained calls + */ + public ExpressionToText setFormatIdentifiers(boolean formatIdetifiers) { + this.formatIdentifiers = formatIdetifiers; + return this; + } + + /** + * Creates a text structure from an expression. + * Uses the default format + * + * @param expression the expression + * @return the text + */ + public Text createText(Expression expression) { + return createText(expression, FormatToExpression.getDefaultFormat()); + } + + /** + * Creates a text structure from an expression + * + * @param expression the expression + * @param format the format to use + * @return the text + */ + public Text createText(Expression expression, FormatToExpression format) { + if (expression instanceof Variable) { + String ident = ((Variable) expression).getIdentifier(); + return formatIdent(ident); + } else if (expression instanceof Constant) { + String value = format.constant(((Constant) expression).getValue()); + return new Simple(value); + } else if (expression instanceof Operation.And) { + return createOperationText((Operation) expression, format.getAndString(), format); + } else if (expression instanceof Operation.Or) { + return createOperationText((Operation) expression, format.getOrString(), format); + } else if (expression instanceof Operation.XOr) { + return createOperationText((Operation) expression, format.getXorString(), format); + } else if (expression instanceof Not) { + return new Decorate(createText(((Not) expression).getExpression(), format), Decorate.Style.OVERLINE); + } else if (expression instanceof NamedExpression) { + NamedExpression ne = (NamedExpression) expression; + Sentence s = new Sentence(); + s.add(formatIdent(ne.getName())); + s.add(Blank.BLANK); + s.add(new Simple(format.getEqual())); + s.add(Blank.BLANK); + s.add(createText(ne.getExpression(), format)); + return s; + } else + return new Simple(expression.toString()); + } + + private Text formatIdent(String ident) { + if (formatIdentifiers) { + try { + return new Parser(ident).parse(); + } catch (ParseException e) { + return new Simple(ident); + } + } else + return new Simple(ident); + } + + private Text createOperationText(Operation op, String opString, FormatToExpression format) { + Sentence s = new Sentence(); + for (Expression e : op.getExpressions()) { + if (s.size() > 0) { + s.add(Blank.BLANK); + if (!opString.isEmpty()) { + s.add(new Simple(opString)); + s.add(Blank.BLANK); + } + } + if (e instanceof Operation) { + s.add(new Simple("(")); + s.add(createText(e, format)); + s.add(new Simple(")")); + } else { + s.add(createText(e, format)); + } + } + return s; + } + +} diff --git a/src/main/java/de/neemann/digital/draw/graphics/text/text/Sentence.java b/src/main/java/de/neemann/digital/draw/graphics/text/text/Sentence.java index 1fa5e69bf..509a9560f 100644 --- a/src/main/java/de/neemann/digital/draw/graphics/text/text/Sentence.java +++ b/src/main/java/de/neemann/digital/draw/graphics/text/text/Sentence.java @@ -84,4 +84,11 @@ public class Sentence implements Text, Iterable { else return list.get(list.size() - 1) instanceof Blank; } + + /** + * @return the size of the sentence + */ + public int size() { + return list.size(); + } } diff --git a/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java b/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java index 9aaa0c417..563ee337b 100644 --- a/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java +++ b/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java @@ -93,7 +93,7 @@ public class TransitionTableCreator { // create the next state result variables for (int i = stateBits - 1; i >= 0; i--) - truthTable.addResult(STATE_VAR+"_" + i + "^n+1"); + truthTable.addResult(STATE_VAR+"_" + i + "^{n+1}"); // add the output variables TreeSet results = new TreeSet<>(); diff --git a/src/main/java/de/neemann/digital/gui/components/karnaugh/KarnaughMapComponent.java b/src/main/java/de/neemann/digital/gui/components/karnaugh/KarnaughMapComponent.java index b3da5af91..67331a68d 100644 --- a/src/main/java/de/neemann/digital/gui/components/karnaugh/KarnaughMapComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/karnaugh/KarnaughMapComponent.java @@ -8,8 +8,6 @@ package de.neemann.digital.gui.components.karnaugh; import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.Not; import de.neemann.digital.analyse.expression.Variable; -import de.neemann.digital.analyse.expression.format.FormatToExpression; -import de.neemann.digital.analyse.expression.format.FormatterException; import de.neemann.digital.analyse.quinemc.BoolTable; import de.neemann.digital.draw.graphics.text.formatter.GraphicsFormatter; import de.neemann.digital.lang.Lang; @@ -23,8 +21,6 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.ArrayList; -import static de.neemann.digital.analyse.expression.Not.not; - /** * JComponent to show a kv map. */ @@ -120,18 +116,17 @@ public class KarnaughMapComponent extends JComponent { gr.setFont(valuesFont); Font headerFont = valuesFont; - try { - int maxHeaderStrWidth = 0; - FontMetrics fontMetrics = gr.getFontMetrics(); - for (Variable v : vars) { - int w = fontMetrics.stringWidth(FormatToExpression.defaultFormat(not(v))); + int maxHeaderStrWidth = 0; + FontMetrics fontMetrics = gr.getFontMetrics(); + for (int i = 0; i < vars.size(); i++) { + final GraphicsFormatter.Fragment fr = getFragment(i, true); + if (fr != null) { + int w = fr.getWidth(); if (w > maxHeaderStrWidth) maxHeaderStrWidth = w; } - if (maxHeaderStrWidth > cellSize) - headerFont = origFont.deriveFont(cellSize * 0.5f * cellSize / maxHeaderStrWidth); - } catch (FormatterException e) { - // can not happen } + if (maxHeaderStrWidth > cellSize) + headerFont = origFont.deriveFont(cellSize * 0.5f * cellSize / maxHeaderStrWidth); xOffs = (width - (kvWidth + 2) * cellSize) / 2; yOffs = (height - (kvHeight + 2) * cellSize) / 2; diff --git a/src/main/java/de/neemann/digital/gui/components/table/BuilderExpressionCreator.java b/src/main/java/de/neemann/digital/gui/components/table/BuilderExpressionCreator.java index b3ced42fb..d90e64ad9 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/BuilderExpressionCreator.java +++ b/src/main/java/de/neemann/digital/gui/components/table/BuilderExpressionCreator.java @@ -55,9 +55,9 @@ public class BuilderExpressionCreator { if (!contained.contains(name)) { contained.add(name); try { - if (name.endsWith("n+1")) { - name = name.substring(0, name.length() - 2); - builder.addSequential(name, ExpressionModifier.modifyExpression(expression, modifier)); + String n = ExpressionListenerJK.isSequentialVar(name); + if (n!=null) { + builder.addSequential(n, ExpressionModifier.modifyExpression(expression, modifier)); } else builder.addCombinatorial(name, ExpressionModifier.modifyExpression(expression, modifier)); } catch (BuilderException e) { diff --git a/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerJK.java b/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerJK.java index 7ac707ed6..bd4b050c6 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerJK.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerJK.java @@ -31,9 +31,11 @@ public class ExpressionListenerJK implements ExpressionListener { public void resultFound(String name, Expression expression) throws FormatterException, ExpressionException { parent.resultFound(name, expression); - if (name.endsWith("n+1")) { - String detName = name.substring(0, name.length() - 2); + String detName = isSequentialVar(name); + + if (detName != null) { DetermineJKStateMachine jk = new DetermineJKStateMachine(detName, expression); + if (detName.endsWith("^n")) detName = detName.substring(0, detName.length() - 2); else @@ -54,6 +56,23 @@ public class ExpressionListenerJK implements ExpressionListener { } + /** + * If the name belogs to a sequential state var, the state vars name is returned. + * Otherwise a null is returned + * + * @param name the name of the variable + * @return the state variable or null + */ + public static String isSequentialVar(String name) { + String detName = null; + if (name.endsWith("n+1")) { + detName = name.substring(0, name.length() - 2); + } else if (name.endsWith("{n+1}")) { + detName = name.substring(0, name.length() - 5) + "n"; + } + return detName; + } + @Override public void close() throws FormatterException, ExpressionException { parent.close(); diff --git a/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerOptimizeJK.java b/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerOptimizeJK.java index 8aa2da245..8df6a63d0 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerOptimizeJK.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerOptimizeJK.java @@ -36,8 +36,8 @@ public class ExpressionListenerOptimizeJK implements ExpressionListener { @Override public void resultFound(String name, Expression expression) throws FormatterException, ExpressionException { - if (name.endsWith("n+1")) { - String varName = name.substring(0, name.length() - 2); + String varName = ExpressionListenerJK.isSequentialVar(name); + if (varName != null) { if (name.equals(lastName)) { int c = new DetermineJKStateMachine(varName, expression).getComplexity(); if (c < lastComplexity) { diff --git a/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerStore.java b/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerStore.java index 2a4a667b8..8fd7d59e0 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerStore.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ExpressionListenerStore.java @@ -7,6 +7,7 @@ package de.neemann.digital.gui.components.table; import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.ExpressionException; +import de.neemann.digital.analyse.expression.NamedExpression; import de.neemann.digital.analyse.expression.format.FormatToExpression; import de.neemann.digital.analyse.expression.format.FormatterException; @@ -106,11 +107,7 @@ public class ExpressionListenerStore implements ExpressionListener { @Override public String toString() { - try { - return name + " = " + FormatToExpression.defaultFormat(expression); - } catch (FormatterException e) { - return name; - } + return FormatToExpression.defaultFormat(new NamedExpression(name, expression)); } } } diff --git a/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java b/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java new file mode 100644 index 000000000..001182e0a --- /dev/null +++ b/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.gui.components.table; + +import de.neemann.digital.analyse.TruthTableTableModel; +import de.neemann.digital.analyse.expression.Expression; +import de.neemann.digital.analyse.expression.ExpressionException; +import de.neemann.digital.analyse.expression.NamedExpression; +import de.neemann.digital.analyse.format.TruthTableFormatterLaTeX; +import de.neemann.digital.draw.graphics.text.formatter.LaTeXFormatter; + +final class LaTeXExpressionListener implements ExpressionListener { + private final StringBuilder sb; + + LaTeXExpressionListener(TruthTableTableModel model) throws ExpressionException { + sb = new StringBuilder(); + if (model.getTable().getRows() <= 256) { + String text = new TruthTableFormatterLaTeX().format(model.getTable()); + sb.append(text); + } + sb.append("\\begin{eqnarray*}\n"); + } + + @Override + public void resultFound(String name, Expression expression) { + sb.append(LaTeXFormatter.format(new NamedExpression(name, expression))) + .append("\\\\\n"); + } + + @Override + public void close() { + sb.append("\\end{eqnarray*}\n"); + } + + @Override + public String toString() { + return sb.toString(); + } +} diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index 64990ac1f..6964b77b2 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -13,11 +13,8 @@ import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.NamedExpression; import de.neemann.digital.analyse.expression.Variable; -import de.neemann.digital.analyse.expression.format.FormatToExpression; -import de.neemann.digital.analyse.expression.format.FormatToTableLatex; import de.neemann.digital.analyse.expression.format.FormatterException; import de.neemann.digital.analyse.expression.modify.*; -import de.neemann.digital.analyse.format.TruthTableFormatterLaTeX; import de.neemann.digital.analyse.quinemc.BoolTableByteArray; import de.neemann.digital.builder.ATF150x.ATFDevice; import de.neemann.digital.builder.ExpressionToFileExporter; @@ -30,6 +27,9 @@ import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.element.Key; import de.neemann.digital.core.element.Keys; import de.neemann.digital.draw.elements.Circuit; +import de.neemann.digital.draw.graphics.text.ParseException; +import de.neemann.digital.draw.graphics.text.Parser; +import de.neemann.digital.draw.graphics.text.formatter.PlainTextFormatter; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.gui.Main; @@ -63,6 +63,8 @@ import java.util.List; import java.util.StringTokenizer; import java.util.prefs.Preferences; +import static de.neemann.digital.analyse.ModelAnalyser.addOne; + /** * */ @@ -133,6 +135,7 @@ public class TableDialog extends JDialog { JComboBox comboBox = new JComboBox<>(TruthTableTableModel.STATENAMES); table.setDefaultEditor(Integer.class, new DefaultCellEditor(comboBox)); table.setDefaultRenderer(Integer.class, new CenterDefaultTableCellRenderer()); + table.getTableHeader().setDefaultRenderer(new StringDefaultTableCellRenderer()); table.setRowHeight(font.getSize() * 6 / 5); table.getInputMap().put(KeyStroke.getKeyStroke("0"), "0_ACTION"); @@ -267,7 +270,7 @@ public class TableDialog extends JDialog { attr.set(Keys.LABEL, name); ElementAttributes modified = new AttributeDialog(this, pos, LIST, attr).showDialog(); if (modified != null) { - final String newName = modified.get(Keys.LABEL).trim().replace(' ', '_'); + final String newName = modified.get(Keys.LABEL).trim().replace(' ', '-'); if (!newName.equals(name)) model.setColumnName(columnIndex, newName); } @@ -317,11 +320,15 @@ public class TableDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { try { - ExpressionListener expressionListener = new LaTeXExpressionListener(model); + final LaTeXExpressionListener laTeXExpressionListener = new LaTeXExpressionListener(model); + ExpressionListener expressionListener = laTeXExpressionListener; if (createJK.isSelected()) expressionListener = new ExpressionListenerJK(expressionListener); lastGeneratedExpressions.replayTo(expressionListener); expressionListener.close(); + + new ShowStringDialog(TableDialog.this, Lang.get("win_table_exportDialog"), + laTeXExpressionListener.toString()).setVisible(true); } catch (ExpressionException | FormatterException e1) { new ErrorMessage(Lang.get("msg_errorDuringCalculation")).addCause(e1).show(TableDialog.this); } @@ -691,7 +698,7 @@ public class TableDialog extends JDialog { BoolTableByteArray val = new BoolTableByteArray(rows); for (int n = 0; n < rows; n++) val.set(n, ((n + 1) >> i) & 1); - truthTable.addResult(v.getIdentifier() + "+1", val); + truthTable.addResult(addOne(v.getIdentifier()), val); i--; } @@ -724,7 +731,7 @@ public class TableDialog extends JDialog { else val.set(n, ((n + 1) >> i) & 1); } - truthTable.addResult(vars.get(vi).getIdentifier() + "+1", val); + truthTable.addResult(addOne(vars.get(vi).getIdentifier()), val); i--; } @@ -754,6 +761,27 @@ public class TableDialog extends JDialog { } } + private final class StringDefaultTableCellRenderer extends DefaultTableCellRenderer { + private StringDefaultTableCellRenderer() { + setHorizontalAlignment(SwingConstants.CENTER); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + label.setBackground(MYGRAY); + + try { + label.setText(PlainTextFormatter.format(new Parser(value.toString()).parse())); + } catch (ParseException e) { + label.setText(value.toString()); + } + setBorder(BorderFactory.createRaisedBevelBorder()); + + return label; + } + } + private final class OutputExpressionListener implements ExpressionListener { private final ArrayList expressions; @@ -819,33 +847,6 @@ public class TableDialog extends JDialog { } } - private final class LaTeXExpressionListener implements ExpressionListener { - private final StringBuilder sb; - - private LaTeXExpressionListener(TruthTableTableModel model) throws ExpressionException { - sb = new StringBuilder(); - if (model.getTable().getRows() <= 256) { - String text = new TruthTableFormatterLaTeX().format(model.getTable()); - sb.append(text); - } - sb.append("\\begin{eqnarray*}\n"); - } - - @Override - public void resultFound(String name, Expression expression) throws FormatterException { - sb.append(FormatToTableLatex.formatIdentifier(name)) - .append("&=&") - .append(FormatToExpression.FORMATTER_LATEX.format(expression)) - .append("\\\\\n"); - } - - @Override - public void close() { - sb.append("\\end{eqnarray*}\n"); - new ShowStringDialog(TableDialog.this, Lang.get("win_table_exportDialog"), sb.toString()).setVisible(true); - } - } - private final class HardwareToolTipAction extends ToolTipAction { private final HardwareDescriptionGenerator generator; diff --git a/src/test/java/de/neemann/digital/analyse/DetermineJKStateMachineTest.java b/src/test/java/de/neemann/digital/analyse/DetermineJKStateMachineTest.java index 087f8a19b..9f70d7afc 100644 --- a/src/test/java/de/neemann/digital/analyse/DetermineJKStateMachineTest.java +++ b/src/test/java/de/neemann/digital/analyse/DetermineJKStateMachineTest.java @@ -7,8 +7,8 @@ package de.neemann.digital.analyse; import de.neemann.digital.analyse.expression.Expression; +import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.expression.format.FormatToExpression; -import de.neemann.digital.analyse.expression.format.FormatterException; import junit.framework.TestCase; import static de.neemann.digital.analyse.expression.Not.not; @@ -28,7 +28,7 @@ public class DetermineJKStateMachineTest extends TestCase { private Expression c; private Expression notc; - public void setUp() throws Exception { + public void setUp() { a = v("a"); nota = not(a); b = v("b"); @@ -47,7 +47,23 @@ public class DetermineJKStateMachineTest extends TestCase { assertFalse(jk.isDFF()); } - private String toStr(Expression expression) throws FormatterException { + public void testIndex() throws Exception { + Variable _a = v("Q_0^n"); + Expression _nota = not(_a); + Expression _b = v("Q_1^n"); + Expression _notb = not(_b); + Expression _c = v("Q_2^n"); + Expression _notc = not(_c); + + Expression e = or(and(_a, _c), and(_nota, _notb)); + + DetermineJKStateMachine jk = new DetermineJKStateMachine(_a.getIdentifier(), e); + assertEquals(toStr(_notb), toStr(jk.getJ())); + assertEquals(toStr(_notc), toStr(jk.getK())); + assertFalse(jk.isDFF()); + } + + private String toStr(Expression expression) { return FormatToExpression.FORMATTER_UNICODE.format(expression); } diff --git a/src/test/java/de/neemann/digital/analyse/LabelNumberingTest.java b/src/test/java/de/neemann/digital/analyse/LabelNumberingTest.java index afcb577ea..bc035f2f7 100644 --- a/src/test/java/de/neemann/digital/analyse/LabelNumberingTest.java +++ b/src/test/java/de/neemann/digital/analyse/LabelNumberingTest.java @@ -13,7 +13,8 @@ public class LabelNumberingTest extends TestCase { assertEquals("test", new LabelNumbering("test").create(name -> false)); assertEquals("test2", new LabelNumbering("test").create(new TestCheck())); assertEquals("test2n", new LabelNumbering("testn").create(new TestCheck())); - assertEquals("test2_n", new LabelNumbering("test_n").create(new TestCheck())); + assertEquals("test_2^n", new LabelNumbering("test^n").create(new TestCheck())); + assertEquals("test_2n", new LabelNumbering("test_n").create(new TestCheck())); } private class TestCheck implements LabelNumbering.Exists { diff --git a/src/test/java/de/neemann/digital/analyse/ModelAnalyserTest.java b/src/test/java/de/neemann/digital/analyse/ModelAnalyserTest.java index 4ed4aa70c..ad17e18ac 100644 --- a/src/test/java/de/neemann/digital/analyse/ModelAnalyserTest.java +++ b/src/test/java/de/neemann/digital/analyse/ModelAnalyserTest.java @@ -170,23 +170,23 @@ public class ModelAnalyserTest extends TestCase { Model model = createModel("dig/analyze/uniqueNames3.dig"); ArrayList ins = new ModelAnalyser(model).getInputs(); assertEquals(2,ins.size()); - assertEquals("Zn",ins.get(0).getName()); - assertEquals("Z1n",ins.get(1).getName()); + assertEquals("Z^n",ins.get(0).getName()); + assertEquals("Z_1^n",ins.get(1).getName()); } public void testAnalyzerUniqueNames4() throws Exception { Model model = createModel("dig/analyze/uniqueNames4.dig"); ArrayList ins = new ModelAnalyser(model).getInputs(); assertEquals(2,ins.size()); - assertEquals("Bn",ins.get(0).getName()); - assertEquals("An",ins.get(1).getName()); + assertEquals("B^n",ins.get(0).getName()); + assertEquals("A^n",ins.get(1).getName()); } public void testAnalyzerMultiBit() throws Exception { Model model = createModel("dig/analyze/multiBitCounter.dig"); TruthTable tt = new ModelAnalyser(model).analyse(); - checkTable(tt.getResult("Q0n+1"), one, zero, one, zero); - checkTable(tt.getResult("Q1n+1"), zero, one, one, zero); + checkTable(tt.getResult("Q_0^{n+1}"), one, zero, one, zero); + checkTable(tt.getResult("Q_1^{n+1}"), zero, one, one, zero); assertEquals("Y1", tt.getResultName(2)); assertEquals("Y0", tt.getResultName(3)); diff --git a/src/test/java/de/neemann/digital/analyse/expression/format/FormatToExpressionTest.java b/src/test/java/de/neemann/digital/analyse/expression/format/FormatToExpressionTest.java index 129743ad1..e158959cc 100644 --- a/src/test/java/de/neemann/digital/analyse/expression/format/FormatToExpressionTest.java +++ b/src/test/java/de/neemann/digital/analyse/expression/format/FormatToExpressionTest.java @@ -10,6 +10,8 @@ import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.NamedExpression; import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.parser.Parser; +import de.neemann.digital.draw.graphics.text.formatter.LaTeXFormatter; +import de.neemann.digital.draw.graphics.text.text.ExpressionToText; import junit.framework.TestCase; import java.util.ArrayList; @@ -29,12 +31,13 @@ public class FormatToExpressionTest extends TestCase { Expression e = and(not(or(not(a), not(b))), not(and(not(a), not(b)))); assertEquals("!(!A || !B) && !(!A && !B)", FormatToExpression.FORMATTER_JAVA.format(e)); - assertEquals("\\nicht{\\nicht{A} \\oder \\nicht{B}} \\und \\nicht{\\nicht{A} \\und \\nicht{B}}", FormatToExpression.FORMATTER_LATEX.format(e)); assertEquals("NOT (NOT A OR NOT B) AND NOT (NOT A AND NOT B)", FormatToExpression.FORMATTER_DERIVE.format(e)); assertEquals("~(~A + ~B) ~(~A ~B)", FormatToExpression.FORMATTER_LOGISIM.format(e)); assertEquals("¬(¬A ∨ ¬B) ∧ ¬(¬A ∧ ¬B)", FormatToExpression.FORMATTER_UNICODE.format(e)); assertEquals("!(!A + !B) * !(!A * !B)", FormatToExpression.FORMATTER_SHORT.format(e)); assertEquals("!(!A + !B) !(!A !B)", FormatToExpression.FORMATTER_SHORTER.format(e)); + + assertEquals("\\overline{\\overline{A} \\oder \\overline{B}} \\und \\overline{\\overline{A} \\und \\overline{B}}", LaTeXFormatter.format(e)); } public void testFormatExp2() throws Exception { @@ -75,8 +78,8 @@ public class FormatToExpressionTest extends TestCase { public void testFormatExpLaTeX() throws Exception { Variable a = new Variable("A_n"); Variable b = new Variable("B_n"); - Expression e = new NamedExpression("Y^n+1", and(a, not(b))); - assertEquals("Y^{n+1} = A_n \\und \\nicht{B_n}", FormatToExpression.FORMATTER_LATEX.format(e)); + Expression e = new NamedExpression("Y^{n+1}", and(a, not(b))); + assertEquals("Y^{n+1} &=& A_n \\und \\overline{B_n}", LaTeXFormatter.format(e)); } public void testFormatTable() throws Exception { @@ -111,7 +114,7 @@ public class FormatToExpressionTest extends TestCase { ArrayList e = new Parser("let sum=(A^B)^C, let c = (A B) + ((A^B) C)").parse(); assertEquals("sum = (A ⊻ B) ⊻ C", FormatToExpression.FORMATTER_UNICODE.format(e.get(0))); assertEquals("c = (A ∧ B) ∨ ((A ⊻ B) ∧ C)", FormatToExpression.FORMATTER_UNICODE.format(e.get(1))); - assertEquals("sum = (A \\xoder B) \\xoder C", FormatToExpression.FORMATTER_LATEX.format(e.get(0))); + assertEquals("sum &=& (A \\xoder B) \\xoder C", LaTeXFormatter.format(e.get(0))); assertEquals("sum = (A $ B) $ C", FormatToExpression.FORMATTER_CUPL.format(e.get(0))); assertEquals("sum = (A ^ B) ^ C", FormatToExpression.FORMATTER_JAVA.format(e.get(0))); assertEquals("sum = (A ^ B) ^ C", FormatToExpression.FORMATTER_SHORT.format(e.get(0))); diff --git a/src/test/java/de/neemann/digital/draw/graphics/text/formatter/PlainTextFormatterTest.java b/src/test/java/de/neemann/digital/draw/graphics/text/formatter/PlainTextFormatterTest.java new file mode 100644 index 000000000..b4310b338 --- /dev/null +++ b/src/test/java/de/neemann/digital/draw/graphics/text/formatter/PlainTextFormatterTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Helmut Neemann + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.draw.graphics.text.formatter; + +import de.neemann.digital.analyse.expression.format.FormatToExpression; +import de.neemann.digital.draw.graphics.text.ParseException; +import de.neemann.digital.draw.graphics.text.Parser; +import junit.framework.TestCase; + +public class PlainTextFormatterTest extends TestCase { + + public void testSimple() throws ParseException { + assertEquals("Hello World", PlainTextFormatter.format(new Parser("Hello World").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("Q", PlainTextFormatter.format(new Parser("Q").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("Q", PlainTextFormatter.format(new Parser("$Q$").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("Q0n+1", PlainTextFormatter.format(new Parser("Q_0^{n+1}").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("Q0n", PlainTextFormatter.format(new Parser("Q_0^n").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("Q0n", PlainTextFormatter.format(new Parser("Q^n_0").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("!Q", PlainTextFormatter.format(new Parser("~{Q}").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("!(A+B)", PlainTextFormatter.format(new Parser("~{A+B}").parse(), FormatToExpression.FORMATTER_JAVA)); + assertEquals("!(!Q)", PlainTextFormatter.format(new Parser("~{~Q}").parse(), FormatToExpression.FORMATTER_JAVA)); + + assertEquals("!a0n", PlainTextFormatter.format(new Parser("~{a_0^n}").parse(), FormatToExpression.FORMATTER_JAVA)); + } + +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/gui/components/table/ExpressionListenerJKTest.java b/src/test/java/de/neemann/digital/gui/components/table/ExpressionListenerJKTest.java index 150d7d9b4..f5913dfc3 100644 --- a/src/test/java/de/neemann/digital/gui/components/table/ExpressionListenerJKTest.java +++ b/src/test/java/de/neemann/digital/gui/components/table/ExpressionListenerJKTest.java @@ -33,4 +33,11 @@ public class ExpressionListenerJKTest extends TestCase { assertEquals("not(A)", exp.getList().get(2).toString()); } + public void testSequentialVar() { + assertEquals(null, ExpressionListenerJK.isSequentialVar("A")); + assertEquals(null, ExpressionListenerJK.isSequentialVar("An")); + assertEquals("An", ExpressionListenerJK.isSequentialVar("An+1")); + assertEquals("An", ExpressionListenerJK.isSequentialVar("A{n+1}")); + } + } diff --git a/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java b/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java new file mode 100644 index 000000000..b7611eab9 --- /dev/null +++ b/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Helmut Neemann + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.gui.components.table; + +import de.neemann.digital.analyse.TruthTable; +import de.neemann.digital.analyse.TruthTableTableModel; +import de.neemann.digital.analyse.expression.ExpressionException; +import de.neemann.digital.analyse.expression.Not; +import de.neemann.digital.analyse.expression.Operation; +import de.neemann.digital.analyse.expression.Variable; +import de.neemann.digital.analyse.quinemc.BoolTableBoolArray; +import junit.framework.TestCase; + +public class LaTeXExpressionListenerTest extends TestCase { + + public void testSimple() throws ExpressionException { + TruthTable tt = new TruthTable() + .addVariable("A") + .addVariable("B") + .addResult("Y", new BoolTableBoolArray(new boolean[]{false, false, true, false})); + TruthTableTableModel model = new TruthTableTableModel(tt); + LaTeXExpressionListener l = new LaTeXExpressionListener(model); + l.resultFound("Y", Operation.and(new Variable("A"), new Not(new Variable("B")))); + l.close(); + + assertEquals("\\begin{center}\n" + + "\\begin{tabular}{cc|c}\n" + + "$A$&$B$&$Y$\\\\\n" + + "\\hline\n" + + "$0$&$0$&$0$\\\\\n" + + "$0$&$1$&$0$\\\\\n" + + "$1$&$0$&$1$\\\\\n" + + "$1$&$1$&$0$\\\\\n" + + "\\end{tabular}\n" + + "\\end{center}\n" + + "\\begin{eqnarray*}\n" + + "Y &=& A \\und \\overline{B}\\\\\n" + + "\\end{eqnarray*}\n", l.toString()); + } + +} \ No newline at end of file