Skip to content

Commit

Permalink
[Math-Parser] Support Unicode exponents (#1494)
Browse files Browse the repository at this point in the history
feat(math-parser): support unicode exponents
  • Loading branch information
Zitrone44 authored Jan 2, 2024
1 parent 8292f7b commit 721ad84
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mulFactor : expo // higher presedence!
;

expo : expo ' '* EXP ' '* SUB? factor
| expo unicode_expo
| factor
;

Expand All @@ -34,6 +35,8 @@ factor : LEFT? OPENING_ROUND_BRACKET ' '* expr ' '* RIGHT? CLOSING_ROUND_BR
| (NUMBER|VAR)
;

unicode_expo : UNICODE_EXPO+
;

NUMBER: FULL DECIMAL?;
FULL: [0-9]+;
Expand Down Expand Up @@ -64,3 +67,4 @@ OPENING_SQUARE_BRACKET: '[';
CLOSING_SQUARE_BRACKET: ']';
LEFT: '\\left';
RIGHT: '\\right';
UNICODE_EXPO: ''|'¹'|'²'|'³'|''|''|''|''|''|'';
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class AstBuilder(val eq: MathParser.EqContext) {
when {
expo.EXP() !== null -> Operation(Operator.EXP, buildExpo(expo.expo()), if (expo.SUB() !== null) UnaryOperation(Operator.SUB, buildFactor(expo.factor())) else buildFactor(expo.factor()))
expo.factor() !== null -> buildFactor(expo.factor())
expo.unicode_expo() !== null -> Operation(Operator.EXP, buildExpo(expo.expo()), Num(expo.unicode_expo().text.map { superscriptMap[it] }.joinToString("")))
else -> throw IllegalArgumentException("not a legal exponential: ${expo.text}")
}

Expand All @@ -85,6 +86,7 @@ class AstBuilder(val eq: MathParser.EqContext) {
}

private val germanFormat = NumberFormat.getNumberInstance(Locale.GERMAN)
private val superscriptMap = mapOf('' to '0', '¹' to '1', '²' to '2', '³' to '3', '' to '4', '' to '5', '' to '6', '' to '7', '' to '8', '' to '9')
init {
germanFormat.maximumFractionDigits = germanFormat.maximumIntegerDigits
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,4 +569,44 @@ internal class MathParserHelperTest {
assertEquals(expected, MathParserHelper.parse("(2^3)^4"))
assertEquals(expected, MathParserHelper.parse("2^3^4"))
}

@Test
fun simpleUnicodeExponentTest() {
val expected = Ast(
Operation(
Operator.EXP,
Num(2),
Num(2)
)
)
assertEquals(expected, MathParserHelper.parse(""))
}

@Test
fun multiCharacterUnicodeExponentTest() {
val expected = Ast(
Operation(
Operator.EXP,
Num(2),
Num(16)
)
)
assertEquals(expected, MathParserHelper.parse("2¹⁶"))
}

@Test
fun complexUnicodeExponentTest() {
val expected = Ast(
Operation(
Operator.EXP,
Operation(
Operator.EXP,
Num(2),
Num(3)
),
Num(4)
)
)
assertEquals(expected, MathParserHelper.parse("(2³)⁴"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,34 @@ internal class SemanticAstComparatorTest {
assertNotNull(SemanticAstComparator(2, RoundingMode.HALF_UP, ignoreNeutralElements = false, applyInverseElements = false, applyCommutativeLaw = false))
assertNotNull(SemanticAstComparator())
}

@Test
fun differentExponentRepresentationTest() {
assertTrue(
semanticAstComparator.compare(
MathParserHelper.parse("a^2"),
MathParserHelper.parse("")
)
)
}

@Test
fun multiCharacterDifferentExponentRepresentationTest() {
assertTrue(
semanticAstComparator.compare(
MathParserHelper.parse("a^{22}"),
MathParserHelper.parse("a²²")
)
)
}

@Test
fun complexDifferentExponentRepresentationTest() {
assertTrue(
semanticAstComparator.compare(
MathParserHelper.parse("2^3^4"),
MathParserHelper.parse("(2³)⁴")
)
)
}
}

0 comments on commit 721ad84

Please sign in to comment.