merged newFormat

This commit is contained in:
hneemann 2019-07-28 18:45:28 +02:00
commit bde8a3bc8f
33 changed files with 581 additions and 356 deletions

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>Tunnel</elementName>
@ -21,7 +22,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_3n</string>
<string>q_3^n</string>
</entry>
<entry>
<string>Inputs</string>
@ -29,7 +30,7 @@
</entry>
<entry>
<string>Default</string>
<int>1</int>
<long>1</long>
</entry>
</elementAttributes>
<pos x="260" y="180"/>
@ -88,7 +89,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_2n</string>
<string>q_2^n</string>
</entry>
<entry>
<string>Inputs</string>
@ -96,7 +97,7 @@
</entry>
<entry>
<string>Default</string>
<int>1</int>
<long>1</long>
</entry>
</elementAttributes>
<pos x="260" y="460"/>
@ -150,7 +151,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_1n</string>
<string>q_1^n</string>
</entry>
<entry>
<string>Inputs</string>
@ -158,7 +159,7 @@
</entry>
<entry>
<string>Default</string>
<int>1</int>
<long>1</long>
</entry>
</elementAttributes>
<pos x="260" y="660"/>
@ -197,7 +198,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_0n</string>
<string>q_0^n</string>
</entry>
<entry>
<string>Inputs</string>

View File

@ -22,7 +22,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_0n</string>
<string>q_0^n</string>
</entry>
</elementAttributes>
<pos x="240" y="280"/>
@ -32,7 +32,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_1n</string>
<string>q_1^n</string>
</entry>
<entry>
<string>Default</string>
@ -46,7 +46,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_2n</string>
<string>q_2^n</string>
</entry>
<entry>
<string>Default</string>
@ -60,7 +60,7 @@
<elementAttributes>
<entry>
<string>Label</string>
<string>q_3n</string>
<string>q_3^n</string>
</entry>
<entry>
<string>Default</string>

View File

@ -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 {

View File

@ -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);
}
/**

View File

@ -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<<i))!=0 ?1:0);
FlipflopD newff = new FlipflopD(label + i, qn, nqn, (def & (1L << i)) != 0 ? 1 : 0);
spinput.addAtTop(qn);
model.add(newff);
newff.setInputs(new ObservableValues(insp.getOutputs().get(i), getClock()));

View File

@ -218,22 +218,25 @@ public class TruthTable {
* Adds a variable
*
* @param name name of the variable
* @return this for chained calls
*/
public void addVariable(String name) {
addVariable(new Variable(name));
public TruthTable addVariable(String name) {
return addVariable(new Variable(name));
}
/**
* Adds a variable
*
* @param var the variable to add
* @return this for chained calls
*/
public void addVariable(Variable var) {
public TruthTable addVariable(Variable var) {
variables.add(var);
for (Result r : results)
r.setValues(BoolTableByteArray.createDoubledValues(r.getValues()));
bitSetter = null;
return this;
}
private BitSetter getBitSetter() {

View File

@ -7,6 +7,8 @@ package de.neemann.digital.analyse.expression;
import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
import java.util.Objects;
/**
*/
public final class Not implements Expression {
@ -102,4 +104,18 @@ public final class Not implements Expression {
public String toString() {
return "not(" + expression + ")";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Not not = (Not) o;
return expression.equals(not.expression);
}
@Override
public int hashCode() {
return Objects.hash(expression);
}
}

View File

@ -6,6 +6,8 @@
package de.neemann.digital.analyse.expression.format;
import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.draw.graphics.text.formatter.PlainTextFormatter;
import de.neemann.digital.draw.graphics.text.text.ExpressionToText;
import java.util.Objects;
@ -17,44 +19,44 @@ import static de.neemann.digital.analyse.expression.Variable.v;
/**
* Used to format an expression to a simple string
*/
public class FormatToExpression implements Formatter {
public final class FormatToExpression implements Formatter {
/**
* Creates a string compatible to Java
*/
public static final FormatToExpression FORMATTER_JAVA = new FormatToExpression("||", "&&", "^", "!", "false", "true");
public static final FormatToExpression FORMATTER_JAVA = new FormatToExpression("||", "&&", "^", "!", "false", "true", "=");
/**
* Creates a string compatible to Derive
*/
public static final FormatToExpression FORMATTER_DERIVE = new FormatToExpression("OR", "AND", "XOR", "NOT ", "false", "true");
public static final FormatToExpression FORMATTER_DERIVE = new FormatToExpression("OR", "AND", "XOR", "NOT ", "false", "true", "=");
/**
* Creates a string compatible to WinCUPL
*/
public static final FormatToExpression FORMATTER_CUPL = new FormatToExpression("#", "&", "$", "!", "'b'0", "'b'1");
public static final FormatToExpression FORMATTER_CUPL = new FormatToExpression("#", "&", "$", "!", "'b'0", "'b'1", "=").setKeepVars();
/**
* Creates a string compatible to Logisim
*/
public static final FormatToExpression FORMATTER_LOGISIM = new FormatToExpression("+", "", "^", "~", "false", "true");
public static final FormatToExpression FORMATTER_LOGISIM = new FormatToExpression("+", "", "^", "~", "false", "true", "=");
/**
* Creates a unicode string
*/
public static final FormatToExpression FORMATTER_UNICODE = new FormatToExpression("\u2228", "\u2227", "\u22BB", "\u00AC", "0", "1");
public static final FormatToExpression FORMATTER_UNICODE = new FormatToExpression("\u2228", "\u2227", "\u22BB", "\u00AC", "0", "1", "=");
/**
* Creates a unicode string with no AND character
*/
public static final FormatToExpression FORMATTER_UNICODE_NOAND = new FormatToExpression("\u2228", "", "\u22BB", "\u00AC", "0", "1");
public static final FormatToExpression FORMATTER_UNICODE_NOAND = new FormatToExpression("\u2228", "", "\u22BB", "\u00AC", "0", "1", "=");
/**
* Creates a short string representation
*/
public static final FormatToExpression FORMATTER_SHORT = new FormatToExpression("+", "*", "^", "!", "0", "1");
public static final FormatToExpression FORMATTER_SHORT = new FormatToExpression("+", "*", "^", "!", "0", "1", "=");
/**
* Creates a short string representation
*/
public static final FormatToExpression FORMATTER_SHORTER = new FormatToExpression("+", "", "^", "!", "0", "1");
public static final FormatToExpression FORMATTER_SHORTER = new FormatToExpression("+", "", "^", "!", "0", "1", "=");
/**
* Creates a LaTeX representation
*/
public static final FormatToExpression FORMATTER_LATEX = new FormatterLatex();
public static final FormatToExpression FORMATTER_LATEX = new FormatToExpression("\\oder", "\\und", "\\xoder", "", "0", "1", "&=&");
private static final Expression TOSTRING_EXPR;
@ -84,9 +86,8 @@ public class FormatToExpression implements Formatter {
*
* @param exp the expression to format
* @return the string representation
* @throws FormatterException FormatterException
*/
public static String defaultFormat(Expression exp) throws FormatterException {
public static String defaultFormat(Expression exp) {
return defaultFormat.format(exp);
}
@ -103,25 +104,24 @@ public class FormatToExpression implements Formatter {
private final String andString;
private final String falseString;
private final String trueString;
private final String equal;
private final String xorString;
private final String notString;
private boolean keepVars;
/**
* Derives a new formatter from the parent
*
* @param parent the parent
*/
public FormatToExpression(FormatToExpression parent) {
this(parent.orString, parent.andString, parent.xorString, parent.notString, parent.falseString, parent.trueString);
}
private FormatToExpression(String orString, String andString, String xorString, String notString, String falseString, String trueString) {
private FormatToExpression(String orString, String andString, String xorString, String notString, String falseString, String trueString, String equal) {
this.orString = orString;
this.andString = andString;
this.xorString = xorString;
this.notString = notString;
this.falseString = falseString;
this.trueString = trueString;
this.equal = equal;
}
private FormatToExpression setKeepVars() {
keepVars = true;
return this;
}
/**
@ -140,60 +140,6 @@ public class FormatToExpression implements Formatter {
return defaultFormat;
}
/**
* Formats the given expression
*
* @param expression the expression
* @return the formated string
* @throws FormatterException FormatterException
*/
@Override
public String format(Expression expression) throws FormatterException {
if (expression instanceof Variable) {
return identifier(((Variable) expression).getIdentifier());
} else if (expression instanceof Constant) {
return constant(((Constant) expression).getValue());
} else if (expression instanceof Not) {
return formatNot((Not) expression);
} else if (expression instanceof Operation.And) {
return formatAnd((Operation.And) expression);
} else if (expression instanceof Operation.Or) {
return formatOr((Operation.Or) expression);
} else if (expression instanceof Operation.XOr) {
return formatXOr((Operation.XOr) expression);
} else if (expression instanceof NamedExpression) {
NamedExpression ne = (NamedExpression) expression;
return identifier(ne.getName()) + " = " + format(ne.getExpression());
} else throw new FormatterException("unknown type " + expression.getClass().getSimpleName());
}
/**
* Formats a not expression
*
* @param expression the nor expression
* @return the formatted string
* @throws FormatterException FormatterException
*/
protected String formatNot(Not expression) throws FormatterException {
if (expression.getExpression() instanceof Operation)
return notString + "(" + format(expression.getExpression()) + ")";
else
return notString + format(expression.getExpression());
}
private String formatAnd(Operation.And expression) throws FormatterException {
return formatOp(expression.getExpressions(), andString);
}
private String formatOr(Operation.Or expression) throws FormatterException {
return formatOp(expression.getExpressions(), orString);
}
private String formatXOr(Operation.XOr expression) throws FormatterException {
return formatOp(expression.getExpressions(), xorString == null ? "^" : xorString); // fixes stored old formats
}
/**
* @return the OR string
*/
@ -216,27 +162,19 @@ public class FormatToExpression implements Formatter {
}
/**
* Formats an operation
*
* @param expressions the expressions
* @param opString the string representation of the operation
* @return the formatted string
* @throws FormatterException FormatterException
* @return the NOT string
*/
private String formatOp(Iterable<Expression> 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);
}
}
}

View File

@ -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());

View File

@ -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 + "}";
}
}

View File

@ -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);
}
}

View File

@ -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<CuplExporter> {
* 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<CuplExporter> {
}
}
try {
if (!builder.getRegistered().isEmpty()) {
out.append("\r\n/* sequential logic */\r\n");
for (Map.Entry<String, Expression> 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<String, Expression> 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<String, Expression> 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<String, Expression> 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();

View File

@ -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<CircuitBuilder> {
fragments.add(new FragmentExpression(Arrays.asList(frJ, frK), fe));
}
}
} catch (ExpressionException | FormatterException e) {
} catch (ExpressionException e) {
throw new BuilderException(e.getMessage());
}
}

View File

@ -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 {

View File

@ -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);

View File

@ -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 "";
}
}

View File

@ -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;
}
}

View File

@ -84,4 +84,11 @@ public class Sentence implements Text, Iterable<Text> {
else
return list.get(list.size() - 1) instanceof Blank;
}
/**
* @return the size of the sentence
*/
public int size() {
return list.size();
}
}

View File

@ -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<String> results = new TreeSet<>();

View File

@ -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;

View File

@ -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) {

View File

@ -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();

View File

@ -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) {

View File

@ -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));
}
}
}

View File

@ -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();
}
}

View File

@ -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<String> 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<Expression> 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;

View File

@ -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);
}

View File

@ -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 {

View File

@ -170,23 +170,23 @@ public class ModelAnalyserTest extends TestCase {
Model model = createModel("dig/analyze/uniqueNames3.dig");
ArrayList<Signal> 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<Signal> 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));

View File

@ -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<Expression> 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)));

View File

@ -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));
}
}

View File

@ -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}"));
}
}

View File

@ -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());
}
}