From ac0b0928e864a34a7b6f43d9ededc1759dd672cd Mon Sep 17 00:00:00 2001 From: miettinen Date: Mon, 13 Jan 2014 08:14:16 +0000 Subject: [PATCH] Sysdyn unit parser to understand ^ (refs #4547) and bugfix to division (refs #4549). git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28621 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../unitParser/UnitCheckingNodeFactory.java | 4 + .../sysdyn/unitParser/UnitParser.jjt | 8 +- .../sysdyn/unitParser/nodes/Factor.java | 118 ++++++++++++++++++ .../sysdyn/unitParser/nodes/Power.java | 38 ++++++ .../sysdyn/unitParser/nodes/Term.java | 3 +- 5 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java index e3db8e8f..2526d473 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java @@ -23,11 +23,13 @@ import org.simantics.sysdyn.unitParser.nodes.ComponentReferenceFull; import org.simantics.sysdyn.unitParser.nodes.Condition; import org.simantics.sysdyn.unitParser.nodes.Divide; import org.simantics.sysdyn.unitParser.nodes.Expression; +import org.simantics.sysdyn.unitParser.nodes.Factor; import org.simantics.sysdyn.unitParser.nodes.ForIndex; import org.simantics.sysdyn.unitParser.nodes.FunctionArguments; import org.simantics.sysdyn.unitParser.nodes.FunctionCall; import org.simantics.sysdyn.unitParser.nodes.IfThenElse; import org.simantics.sysdyn.unitParser.nodes.Multiplication; +import org.simantics.sysdyn.unitParser.nodes.Power; import org.simantics.sysdyn.unitParser.nodes.RelOp; import org.simantics.sysdyn.unitParser.nodes.Relation; import org.simantics.sysdyn.unitParser.nodes.Term; @@ -40,6 +42,7 @@ public class UnitCheckingNodeFactory { static { constructors.put("relation", Relation.class); constructors.put("term", Term.class); + constructors.put("factor", Factor.class); constructors.put("arithmetic_expression", Arithmetic.class); constructors.put("ifthenelse", IfThenElse.class); constructors.put("array_definition", ArrayDefinition.class); @@ -48,6 +51,7 @@ public class UnitCheckingNodeFactory { constructors.put("value", Value.class); + constructors.put("power", Power.class); constructors.put("divide", Divide.class); constructors.put("multiplication", Multiplication.class); constructors.put("add_op", AddOp.class); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt index 8c04b8d2..60acd1a6 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt @@ -132,14 +132,18 @@ void add_op() : { void term() : { } { - factor() ( (multiplication() | divide()) factor() )* + ( LOOKAHEAD(primary() power()) factor() | primary() ) ( (multiplication() | divide()) ( LOOKAHEAD(primary() power()) factor() | primary()) )* } void factor() : { } { - primary() ( "^" primary() | ".^" primary() )? + primary() power() primary() } +void power() : { +} { + "^" | ".^" +} void multiplication() : { } { "*" | ".*" diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java new file mode 100644 index 00000000..6e5b1fe8 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2014 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.unitParser.nodes; + +import java.util.HashMap; + +import org.simantics.sysdyn.unitParser.Token; +import org.simantics.sysdyn.unitParser.UnitCheckingException; +import org.simantics.sysdyn.unitParser.UnitCheckingNode; +import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; + +/** + * See UnitCheckingNodeFactory for mapping + * @author Tuomas Miettinen + * @author Teemu Lempinen + * + */ +public class Factor extends UnitCheckingNode { + + public Factor(int id) { + super(id); + } + + @Override + public UnitResult getUnits(HashMap units) throws UnitCheckingException { + UnitResult result = new UnitResult(); + + UnitCheckingNode current = null; + UnitCheckingNode operator = null; + UnitCheckingNode base = null; + + for(int i = 0; i < jjtGetNumChildren(); i++) { + current = ((UnitCheckingNode)jjtGetChild(i)); + UnitResult currentUnits = current.getUnits(units); + + if(currentUnits.getUnitType() == UnitType.ANY) { + result = new UnitResult(); + result.setUnitType(UnitType.ANY); + return result; + } else if(currentUnits.getUnitType() == UnitType.OPERATOR) { + continue; + } else if(base == null) { + base = current; + continue; + } else { + operator = ((UnitCheckingNode)jjtGetChild(i-1)); + + if(operator instanceof Power) { + UnitType unitType = currentUnits.getUnitType(); + if(unitType == UnitType.SCALAR) { + int exponent; + UnitResult baseUnits = base.getUnits(units); + try { + exponent = Integer.valueOf(currentUnits.getFullUnit()); + } catch (NumberFormatException e) { + exponent = 1; /* It's a bit of a corner case if someone want's to use + an arithmetic expression other than a constant in the exponent. */ + } + + if (exponent < 0) { + for (int j = 0; j > exponent; --j) { + // Negative exponent turns the base number around. + result.addAllDividers(baseUnits.getDividents()); + result.addAllDividents(baseUnits.getDividers()); + result.append(operator.printNode()); + result.append(baseUnits.getFullUnit()); + } + result.setUnitType(baseUnits.getUnitType()); + } else if (exponent > 0) { + result.appendResult(baseUnits); + for (int j = 1; j < exponent; ++j) { + result.addAllDividents(baseUnits.getDividents()); + result.addAllDividers(baseUnits.getDividers()); + result.append(operator.printNode()); + result.append(baseUnits.getFullUnit()); + } + result.setUnitType(baseUnits.getUnitType()); + } // 0 is a corner case + } + } + } + } +// System.out.println("Term: " + printNode() + " [" + result.getFullUnit() + " : " + result.getUnitType() + "]"); + return result; + } + + @Override + public String printNode() { + StringBuilder sb = new StringBuilder(); + Token token = jjtGetFirstToken(); + sb.append(token.image); + + Token prevToken = null; + while(token != null && !token.equals(jjtGetLastToken())) { + prevToken = token; + token = token.next; + if(!token.image.equals("[") + && !token.image.equals("]") + && !prevToken.image.equals("[") + && !prevToken.image.equals("]") + && !token.image.equals(".") + && !prevToken.image.equals(".")) + sb.append(" "); + sb.append(token.image); + } + return sb.toString(); + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java new file mode 100644 index 00000000..14799461 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2014 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.unitParser.nodes; + +import java.util.HashMap; + +import org.simantics.sysdyn.unitParser.UnitCheckingException; +import org.simantics.sysdyn.unitParser.UnitCheckingNode; +import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; + +/** + * See UnitCheckingNodeFactory for mapping + * @author Tuomas Miettinen + * + */ +public class Power extends UnitCheckingNode { + + public Power(int id) { + super(id); + } + + @Override + public UnitResult getUnits(HashMap units) throws UnitCheckingException { + UnitResult result = super.getUnits(units); + result.setUnitType(UnitType.OPERATOR); + return result; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java index d8b454e6..77f9c409 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java @@ -62,9 +62,8 @@ public class Term extends UnitCheckingNode { } } else if(operator instanceof Divide) { result.append(operator.printNode()); - result.addAllDividers(currentUnits.getDividers()); + result.addAllDividents(currentUnits.getDividers()); result.addAllDividers(currentUnits.getDividents()); - UnitType unitType = currentUnits.getUnitType(); result.setUnitType(unitType); if(unitType == UnitType.SCALAR || unitType == UnitType.DMNL) -- 2.47.1