]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/units/internal/parser/UnitParser.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / units / internal / parser / UnitParser.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/units/internal/parser/UnitParser.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/units/internal/parser/UnitParser.java
new file mode 100644 (file)
index 0000000..31723aa
--- /dev/null
@@ -0,0 +1,149 @@
+/*******************************************************************************\r
+ *  Copyright (c) 2010 Association for Decentralized Information Management in\r
+ *  Industry THTH ry.\r
+ *  All rights reserved. This program and the accompanying materials\r
+ *  are made available under the terms of the Eclipse Public License v1.0\r
+ *  which accompanies this distribution, and is available at\r
+ *  http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ *  Contributors:\r
+ *      VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.units.internal.parser;
+
+import org.simantics.databoard.units.internal.UnitParseException;\r
+
+public abstract class UnitParser {
+
+       String string;
+       int pos;
+       
+       int nextChar;
+       int sign;
+       
+       public UnitParser() {
+       }
+
+       void next() {
+               ++pos;
+               if(pos >= string.length())
+                       nextChar = -1;
+               else
+                       nextChar = string.charAt(pos);
+       }
+       
+       public void unit(String string, int sign) throws UnitParseException {
+               this.string = string;
+               this.pos = -1;
+               this.sign = sign;
+               next();
+               
+               expression();
+               expect(-1);
+       }
+       
+       /* Grammar
+        * 
+        * unit_expression: unit_numerator [ "/" unit_denominator ]
+        * unit_numerator: "1" | unit_factors | "(" unit_expression ")"
+        * unit_denominator: unit_factor | "(" unit_expression ")"
+        * unit_factors: unit_factor [ "." unit_factors ]
+        * unit_factor: unit_operand [ unit_exponent ]
+        * unit_exponent: [ "+" | "-" ] integer
+        * unit_operand: unit_symbol | unit_prefix unit_symbol 
+        */
+       
+       void expression() throws UnitParseException {
+               numerator();
+               if(nextChar == '/') {
+                       next();
+                       denominator();
+               }               
+       }
+       
+       void numerator() throws UnitParseException {
+               if(nextChar == '1')
+                       next();
+               else if(nextChar == '(') {
+                       next();
+                       expression();
+                       skip(')');
+               }
+               else
+                       factors();
+       }
+
+       void denominator() throws UnitParseException {
+               sign = -sign;
+               if(nextChar == '(') {
+                       next();
+                       expression();
+                       skip(')');
+               }
+               else
+                       factor();
+               sign = -sign;
+       }
+       
+       void factors() throws UnitParseException {
+               while(true) {
+                       factor();
+                       if(nextChar == '.')
+                               next();
+                       else
+                           break;
+               }
+       }
+       
+       void factor() throws UnitParseException {
+               // Base
+               int factorBegin = pos;
+               while((nextChar >= 'a' && nextChar <= 'z') || (nextChar >= 'A' && nextChar <= 'Z') || (nextChar=='ยต') || nextChar=='(' || nextChar==')' || nextChar=='%') 
+                       next();
+               int exponentBegin = pos;
+               if(factorBegin == exponentBegin)
+                       throw new UnitParseException(string, 
+                                       "Expected base unit name, but got " + charName(nextChar) + " at position " + pos + ".");        
+               String baseUnit = string.substring(factorBegin, exponentBegin);
+               
+               // Exponent
+               if(nextChar == '-' || nextChar == '+' || (nextChar >= '0' && nextChar <= '9')) {
+                       next();
+                       while(nextChar >= '0' && nextChar <= '9')
+                               next();
+               }
+               int exponentEnd = pos;
+               if(exponentEnd > exponentBegin) {
+                       String exponentString = string.substring(exponentBegin, exponentEnd);
+                       try {
+                               visit(baseUnit, sign * Integer.parseInt(exponentString));
+                       } catch(NumberFormatException e) {
+                               throw new UnitParseException(string, 
+                                               "Invalid exponent \"" + exponentString + "\" at position " + pos + ".");        
+                       }
+               }
+               else
+                       visit(baseUnit, sign);
+       }
+                       
+       private void skip(char c) throws UnitParseException {
+               expect(c);                      
+               next();
+       }
+       
+       private static String charName(int c) {
+               if(c >= 0)
+                       return "'" + Character.toString((char)c) + "'";
+               else
+                       return "end of unit";
+       }
+       
+       private void expect(int c) throws UnitParseException {
+               if(nextChar != c)
+                       throw new UnitParseException(string, 
+                                       "Expected " + charName(c) + ", but got " + charName(nextChar) + " at position " + pos + ".");   
+       }
+       
+       public abstract void visit(String baseUnit, int exponent);
+       
+}