
com.hwaipy.quantity.QuantityParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Quantity Show documentation
Show all versions of Quantity Show documentation
For calculation of quantities and units.
The newest version!
package com.hwaipy.quantity;
/**
* @author Hwaipy 2015-3-17
*/
class QuantityParser {
private final String quantityString;
public QuantityParser(String quantityString) {
this.quantityString = quantityString;
}
public Quantity parse() throws QuantityParseException {
Quantity quantity = tryExtractQuantity();
if (position < quantityString.length()) {
throw new QuantityParseException();
}
return quantity;
}
public Unit parseUnit(boolean withFactor) throws QuantityParseException {
double factor = 1;
if (withFactor) {
factor = tryExtractNumber();
if (Double.isNaN(factor)) {
factor = 1;
}
}
Unit unit = tryExtractUnit();
return new UnitBuilder(unit).times(factor).createUnit();
}
private int position = 0;
public double tryExtractNumber() {
int p0 = position;
String integralString = tryExtractInteger(true);
String mantissaString = null;
String powerString = null;
if (isNext('.')) {
position++;
mantissaString = tryExtractInteger(false);
}
if (integralString.length() == 0 || (integralString.length() == 1 && ("+".equals(integralString) || "-".equals(integralString)))) {
if (mantissaString == null || mantissaString.length() == 0) {
position = p0;
return Double.NaN;
}
}
String valueString = integralString;
int p1 = position;
if (isNext('e') || isNext('E')) {
position++;
powerString = tryExtractInteger(true);
}
if (mantissaString != null) {
valueString += "." + mantissaString;
}
if (powerString == null) {
return Double.parseDouble(valueString);
}
else if (powerString.length() == 0 || (powerString.length() == 1 && ("+".equals(powerString) || "-".equals(powerString)))) {
position = p1;
return Double.parseDouble(valueString);
}
else {
return Double.parseDouble(valueString + "E" + powerString);
}
}
public Unit tryExtractUnit() {
UnitBuilder unitBuilder = new UnitBuilder();
while (position < quantityString.length()) {
trim();
int p = position;
boolean powerUp = true;
char c = quantityString.charAt(position);
if (c == '/') {
powerUp = false;
position++;
}
else if (c == '.' || c == '*' || c == '⋅' || c == '×') {
position++;
}
Unit unit = tryExtractOneUnit();
if (unit == null) {
position = p;
break;
}
else {
if (powerUp) {
unitBuilder.times(unit);
}
else {
unitBuilder.divide(unit);
}
}
}
return unitBuilder.createUnit();
}
public Quantity tryExtractQuantity() {
double value = tryExtractNumber();
if (Double.isNaN(value)) {
return null;
}
Unit unit = tryExtractUnit();
return new Quantity(value, unit);
}
public String restString() {
return quantityString.substring(position);
}
private String tryExtractInteger(boolean withSign) {
StringBuilder sb = new StringBuilder();
while (position < quantityString.length()) {
char c = quantityString.charAt(position);
if (c == '+' || c == '-') {
if (withSign && sb.length() == 0) {
position++;
sb.append(c);
}
else {
break;
}
}
else if (c == ',' || c == ' ' || c == '\t') {
position++;
}
else {
char digit = digit(c);
if (digit > 0) {
position++;
sb.append(digit);
}
else {
break;
}
}
}
return sb.toString();
}
private boolean isNext(char target) {
if (position < quantityString.length()) {
char c = quantityString.charAt(position);
return c == target;
}
else {
return false;
}
}
private char digit(char c) {
if (c >= '0' && c <= '9') {
return c;
}
else if (c >= '0' && c <= '9') {
return (char) (c - ('0' - '0'));
}
else {
return 0;
}
}
private Unit tryExtractOneUnit() {
int p0 = position;
String token = tryExtractOneToken();
if (token.length() == 0) {
position = p0;
return null;
}
else {
Unit baseUnit = tryParseOneUnit(token);
if (baseUnit == null) {
position = p0;
return null;
}
else {
if (isNext('^')) {
int p1 = position;
position++;
String powerString = tryExtractInteger(true);
if (powerString.length() == 0 || (powerString.length() == 1 && ("+".equals(powerString) || "-".equals(powerString)))) {
position = p1;
return baseUnit;
}
else {
int power = Integer.parseInt(powerString);
return baseUnit.power(power);
}
}
else {
return baseUnit;
}
}
}
}
private void trim() {
while (position < quantityString.length()) {
char c = quantityString.charAt(position);
if (c == ' ' || c == '\t') {
position++;
}
else {
break;
}
}
}
private String tryExtractOneToken() {
StringBuilder sb = new StringBuilder();
while (position < quantityString.length()) {
char c = quantityString.charAt(position);
if (c == ' ' || c == '\t' || c == '+' || c == '-' || c == ',' || c == '.'
|| c == '*' || c == '⋅' || c == '×' || c == '/' || c == '^') {
}
else {
switch (Character.getType(c)) {
case Character.COMBINING_SPACING_MARK:
case Character.CONNECTOR_PUNCTUATION:
case Character.CURRENCY_SYMBOL:
case Character.DASH_PUNCTUATION:
case Character.ENCLOSING_MARK:
case Character.START_PUNCTUATION:
case Character.END_PUNCTUATION:
case Character.FINAL_QUOTE_PUNCTUATION:
case Character.FORMAT:
case Character.INITIAL_QUOTE_PUNCTUATION:
case Character.LETTER_NUMBER:
case Character.LOWERCASE_LETTER:
case Character.MATH_SYMBOL:
case Character.MODIFIER_LETTER:
case Character.MODIFIER_SYMBOL:
case Character.NON_SPACING_MARK:
case Character.OTHER_LETTER:
case Character.OTHER_NUMBER:
case Character.OTHER_PUNCTUATION:
case Character.OTHER_SYMBOL:
case Character.SURROGATE:
case Character.TITLECASE_LETTER:
case Character.UPPERCASE_LETTER:
position++;
sb.append(c);
continue;
default:
}
}
break;
}
return sb.toString();
}
private Unit tryParseOneUnit(String unitString) {
for (int split = 0; split < unitString.length(); split++) {
String prefixString = unitString.substring(0, split);
String tokenString = unitString.substring(split);
UnitPrefix prefix = UnitPrefixes.get(prefixString);
Unit unit = Units.get(tokenString);
if (prefix != null && unit != null && (prefix == UnitPrefixes.none || unit.hasPrefix())) {
return unit.prefix(prefix);
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy