Commit f6f16d28 by Luc Maisonobe

### Fixed associativity in units parsing.

`Fixes #776`
parent cc4ef9ea
 ... ... @@ -21,6 +21,9 @@ Fixed associativity in units parsing. TimeStampedFieldPVCoordinates now implements FieldTimeStamped. ... ...
 ... ... @@ -26,14 +26,13 @@ import org.hipparchus.fraction.Fraction; * The special case "n/a" corresponds to {@link PredefinedUnit#NONE}. *

*
*   unit         → "n/a"        | chain
*   chain        → operand operation
*   operand      → '√' simple   | simple power
*   operation    → '*' chain    | '/' chain    | ε
*   power        → '^' exponent | ε
*   exponent     → integer      | '(' integer denominator ')'
*   denominator  → '/' integer  | ε
*   simple       → predefined   | '(' chain ')'
*   unit         ::=  "n/a"        | chain
*   chain        ::=  operand { ('*' | '/') operand }
*   operand      ::=  '√' simple   | simple power
*   power        ::=  '^' exponent | ε
*   exponent     ::=  integer      | '(' integer denominator ')'
*   denominator  ::=  '/' integer  | ε
*   simple       ::=  predefined   | '(' chain ')'
*
*

* This parses correctly units like MHz, km/√d, kg.m.s⁻¹, µas^(2/5)/(h**(2)×m)³, km/√(kg.s), √kg*km** (3/2) /(µs^2*Ω⁻⁷). ... ... @@ -73,7 +72,18 @@ class Parser { * @return chain unit */ private static Unit chain(final Lexer lexer) { return operation(operand(lexer), lexer); Unit chain = operand(lexer); for (Token token = lexer.next(); token != null; token = lexer.next()) { if (checkType(token, TokenType.MULTIPLICATION)) { chain = chain.multiply(null, operand(lexer)); } else if (checkType(token, TokenType.DIVISION)) { chain = chain.divide(null, operand(lexer)); } else { lexer.pushBack(); break; } } return chain; } /** Parse an operand. ... ... @@ -93,23 +103,6 @@ class Parser { } } /** Parse an operation. * @param lhs left hand side unit * @param lexer lexer providing tokens * @return simple unit */ private static Unit operation(final Unit lhs, final Lexer lexer) { final Token token = lexer.next(); if (checkType(token, TokenType.MULTIPLICATION)) { return lhs.multiply(null, chain(lexer)); } else if (checkType(token, TokenType.DIVISION)) { return lhs.divide(null, chain(lexer)); } else { lexer.pushBack(); return lhs; } } /** Parse a power operation. * @param lexer lexer providing tokens * @return exponent ... ...

 ... ... @@ -79,6 +79,19 @@ public class ParserTest { new Fraction(-1, 2), Fraction.ONE, new Fraction(-1, 2), Fraction.ZERO); } @Test public void testLeftAssociativity() { checkReference("(kg/m)/s²", 1.0, Fraction.ONE, Fraction.MINUS_ONE, new Fraction(-2), Fraction.ZERO); checkReference("kg/(m/s²)", 1.0, Fraction.ONE, Fraction.MINUS_ONE, Fraction.TWO, Fraction.ZERO); checkReference("kg/m/s²", 1.0, Fraction.ONE, Fraction.MINUS_ONE, new Fraction(-2), Fraction.ZERO); } @Test public void testEmpty() { expectFailure(""); ... ...
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!