diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index ad082640c..096529c19 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -123,14 +123,14 @@ QUIZ_CASE(equation_solve) { const char * solutions10[] = {"1", "0"}; assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions10, 2); - quiz_assert(UCodePointLeftSuperscript == '\022'); - quiz_assert(UCodePointLeftSuperscript == '\x12'); - quiz_assert(UCodePointRightSuperscript == '\023'); - quiz_assert(UCodePointRightSuperscript == '\x13'); + quiz_assert(UCodePointLeftSystemParenthesis == '\022'); + quiz_assert(UCodePointLeftSystemParenthesis == '\x12'); + quiz_assert(UCodePointRightSystemParenthesis == '\023'); + quiz_assert(UCodePointRightSystemParenthesis == '\x13'); // x^2+x+1=3×x^2+pi×x-√(5) const char * equations11[] = {"x^2+x+1=3×x^2+π×x-√(5)", 0}; - const char * solutions11[] = {"(√(π\0222\023-2·π+8·√(5)+9)-π+1)/(4)", "(-√(π\0222\023-2·π+8·√(5)+9)-π+1)/(4)", "π\0222\023-2·π+8·√(5)+9"}; + const char * solutions11[] = {"(√(π^\0222\023-2·π+8·√(5)+9)-π+1)/(4)", "(-√(π^\0222\023-2·π+8·√(5)+9)-π+1)/(4)", "π^\0222\023-2·π+8·√(5)+9"}; assert_equation_system_exact_solve_to(equations11, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions11, 3); // TODO @@ -231,18 +231,18 @@ QUIZ_CASE(equation_solve_complex_format) { Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar); // x+𝐢 = 0 --> x = e^(-π/2×i) - const char * solutions0Polar[] = {"ℯ\x12-(π)/(2)·𝐢\x13"}; + const char * solutions0Polar[] = {"ℯ^\x12-(π)/(2)·𝐢\x13"}; assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1); // x+√(-1) = 0 --> x = e^(-π/2×𝐢) assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1); // x^2+x+1=0 - const char * solutions2Polar[] = {"ℯ\x12-(2·π)/(3)·𝐢\x13","ℯ\x12(2·π)/(3)·𝐢\x13", "3·ℯ\x12π·𝐢\x13"}; + const char * solutions2Polar[] = {"ℯ^\x12-(2·π)/(3)·𝐢\x13","ℯ^\x12(2·π)/(3)·𝐢\x13", "3·ℯ^\x12π·𝐢\x13"}; assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2Polar, 3); // x^2-√(-1)=0 - const char * solutions3Polar[] = {"ℯ\x12-(3·π)/(4)·𝐢\x13", "ℯ\x12(π)/(4)·𝐢\x13", "4·ℯ\x12(π)/(2)·𝐢\x13"}; + const char * solutions3Polar[] = {"ℯ^\x12-(3·π)/(4)·𝐢\x13", "ℯ^\x12(π)/(4)·𝐢\x13", "4·ℯ^\x12(π)/(2)·𝐢\x13"}; assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3Polar, 3); } diff --git a/ion/include/ion/unicode/code_point.h b/ion/include/ion/unicode/code_point.h index e8b7cb5aa..a736160d0 100644 --- a/ion/include/ion/unicode/code_point.h +++ b/ion/include/ion/unicode/code_point.h @@ -28,10 +28,8 @@ static constexpr CodePoint UCodePointLineFeed = 0xa; // 0x11 to 0x15 are not used, so we can use them for another purpose static constexpr CodePoint UCodePointEmpty = 0x11; // Used to be parsed into EmptyExpression -static constexpr CodePoint UCodePointLeftSuperscript = 0x12; // Used to parse Power -static constexpr CodePoint UCodePointRightSuperscript = 0x13; // Used to parse Power -static constexpr CodePoint UCodePointLeftSystemParenthesis = 0x14; // Used for serialization -static constexpr CodePoint UCodePointRightSystemParenthesis = 0x15; // Used for serialization +static constexpr CodePoint UCodePointLeftSystemParenthesis = 0x12; // Used for serialization +static constexpr CodePoint UCodePointRightSystemParenthesis = 0x13; // Used for serialization static constexpr CodePoint UCodePointMiddleDot = 0xb7; // · static constexpr CodePoint UCodePointMultiplicationSign = 0xd7; // × diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index cc9f502d3..62e79e9d8 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -58,11 +58,10 @@ Expression Parser::parseUntil(Token::Type stoppingType) { &Parser::parseUnexpected, // Token::EndOfStream &Parser::parseStore, // Token::Store &Parser::parseEqual, // Token::Equal - &Parser::parseUnexpected, // Token::RightSuperscript + &Parser::parseUnexpected, // Token::RightSystemParenthesis &Parser::parseUnexpected, // Token::RightBracket &Parser::parseUnexpected, // Token::RightParenthesis &Parser::parseUnexpected, // Token::RightBrace - &Parser::parseUnexpected, // Token::RightSystemParenthesis &Parser::parseUnexpected, // Token::Comma &Parser::parsePlus, // Token::Plus &Parser::parseMinus, // Token::Minus @@ -71,7 +70,7 @@ Expression Parser::parseUntil(Token::Type stoppingType) { &Parser::parseImplicitTimes, // Token::ImplicitTimes &Parser::parseCaret, // Token::Power &Parser::parseBang, // Token::Bang - &Parser::parseLeftSuperscript, // Token::LeftSuperscript + &Parser::parseCaretWithParenthesis, // Token::CaretWithParenthesis &Parser::parseMatrix, // Token::LeftBracket &Parser::parseLeftParenthesis, // Token::LeftParenthesis &Parser::parseUnexpected, // Token::LeftBrace @@ -215,6 +214,24 @@ void Parser::parseCaret(Expression & leftHandSide, Token::Type stoppingType) { } } +void Parser::parseCaretWithParenthesis(Expression & leftHandSide, Token::Type stoppingType) { + if (leftHandSide.isUninitialized()) { + m_status = Status::Error; // Power must have a left operand + return; + } + Token::Type endToken = Token::Type::RightSystemParenthesis; + Expression rightHandSide = parseUntil(endToken); + if (m_status != Status::Progress) { + return; + } + if (!popTokenIfType(endToken)) { + m_status = Status::Error; // Right system parenthesis missing + return; + } + leftHandSide = Power::Builder(leftHandSide, rightHandSide); + isThereImplicitMultiplication(); +} + void Parser::parseEqual(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Equal must have a left operand @@ -259,23 +276,6 @@ void Parser::parseStore(Expression & leftHandSide, Token::Type stoppingType) { leftHandSide = Store::Builder(leftHandSide, static_cast(rightHandSide)); } -void Parser::parseLeftSuperscript(Expression & leftHandSide, Token::Type stoppingType) { - if (leftHandSide.isUninitialized()) { - m_status = Status::Error; // Power must have a left operand - return; - } - Expression rightHandSide = parseUntil(Token::RightSuperscript); - if (m_status != Status::Progress) { - return; - } - if (!popTokenIfType(Token::RightSuperscript)) { - m_status = Status::Error; // Right superscript marker missing. - return; - } - leftHandSide = Power::Builder(leftHandSide, rightHandSide); - isThereImplicitMultiplication(); -} - bool Parser::parseBinaryOperator(const Expression & leftHandSide, Expression & rightHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Left-hand side missing. diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index dd08a501a..3bbc9c917 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -60,6 +60,7 @@ private: void parseSlash(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseImplicitTimes(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseCaret(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseCaretWithParenthesis(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseEqual(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseStore(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseLeftSuperscript(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); diff --git a/poincare/src/parsing/token.h b/poincare/src/parsing/token.h index 2401020eb..06fd47738 100644 --- a/poincare/src/parsing/token.h +++ b/poincare/src/parsing/token.h @@ -24,13 +24,10 @@ public: * token of lesser precedence than Equal, and this prevents expressions * such as "3=4>a". Tokenizer::parseStore uses a special algorithm that * prevents (3>4=a). */ - RightSuperscript, - /* Superscript marks the limit of a power. For instance: - * 2 LeftSuperscript 3! RightSuperscript ! is (2^(3!))! */ + RightSystemParenthesis, RightBracket, RightParenthesis, RightBrace, - RightSystemParenthesis, Comma, Plus, Minus, @@ -43,7 +40,7 @@ public: * in order to allow the Parser to insert such Tokens where needed. */ Caret, Bang, - LeftSuperscript, + CaretWithParenthesis, LeftBracket, LeftParenthesis, LeftBrace, diff --git a/poincare/src/parsing/tokenizer.cpp b/poincare/src/parsing/tokenizer.cpp index 37f8b6497..2f7ce02ac 100644 --- a/poincare/src/parsing/tokenizer.cpp +++ b/poincare/src/parsing/tokenizer.cpp @@ -145,14 +145,11 @@ Token Tokenizer::popToken() { return Token(Token::RightSystemParenthesis); } if (c == '^') { + if (canPopCodePoint(UCodePointLeftSystemParenthesis)) { + return Token(Token::CaretWithParenthesis); + } return Token(Token::Caret); } - if (c == UCodePointLeftSuperscript) { - return Token(Token::LeftSuperscript); - } - if (c == UCodePointRightSuperscript) { - return Token(Token::RightSuperscript); - } if (c == '!') { return Token(Token::Bang); } diff --git a/poincare/src/vertical_offset_layout.cpp b/poincare/src/vertical_offset_layout.cpp index 7121c14bc..ed5f46cc3 100644 --- a/poincare/src/vertical_offset_layout.cpp +++ b/poincare/src/vertical_offset_layout.cpp @@ -173,13 +173,14 @@ int VerticalOffsetLayoutNode::serialize(char * buffer, int bufferSize, Preferenc return numberOfChar; } assert(m_position == Position::Superscript); - /* If the layout is a superscript, write: - * "UCodePointLeftSuperscript indice UCodePointRightSuperscript" */ - int numberOfChar = SerializationHelper::CodePoint(buffer, bufferSize, UCodePointLeftSuperscript); + // If the layout is a superscript, write: '^' 'System(' indice 'System)' + int numberOfChar = SerializationHelper::CodePoint(buffer, bufferSize, '^'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + numberOfChar += SerializationHelper::CodePoint(buffer+numberOfChar, bufferSize-numberOfChar, UCodePointLeftSystemParenthesis); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += const_cast(this)->indiceLayout()->serialize(buffer+numberOfChar, bufferSize-numberOfChar, floatDisplayMode, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - numberOfChar += SerializationHelper::CodePoint(buffer+numberOfChar, bufferSize-numberOfChar, UCodePointRightSuperscript); + numberOfChar += SerializationHelper::CodePoint(buffer+numberOfChar, bufferSize-numberOfChar, UCodePointRightSystemParenthesis); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar] = 0; diff --git a/poincare/test/vertical_offset_layout.cpp b/poincare/test/vertical_offset_layout.cpp index 7da0bbae7..7b49f98c3 100644 --- a/poincare/test/vertical_offset_layout.cpp +++ b/poincare/test/vertical_offset_layout.cpp @@ -14,7 +14,7 @@ QUIZ_CASE(poincare_vertical_offset_layout_serialize) { VerticalOffsetLayoutNode::Position::Superscript ) ); - assert(UCodePointLeftSuperscript == '\x12'); - assert(UCodePointRightSuperscript == '\x13'); - assert_expression_layout_serialize_to(layout, "2\x12x+5\x13"); + assert(UCodePointLeftSystemParenthesis == '\x12'); + assert(UCodePointRightSystemParenthesis == '\x13'); + assert_expression_layout_serialize_to(layout, "2^\x12x+5\x13"); }