X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Funits%2Finternal%2Fparser%2FUnitParser.java;fp=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Funits%2Finternal%2Fparser%2FUnitParser.java;h=31723aacc9e30e98f329686fbe36b4dba13e44bf;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git 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 index 000000000..31723aacc --- /dev/null +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/units/internal/parser/UnitParser.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2010 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.databoard.units.internal.parser; + +import org.simantics.databoard.units.internal.UnitParseException; + +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); + +}