mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Fix VerticalOffsetLayout serialization
"2^3 !" would be serialized as "2^3*!", which is wrong. It is now serialized as "2 Ion::Charset::Superscript 3 Ion::Charset::Superscript !" and parsed correctly.
This commit is contained in:
@@ -27,7 +27,8 @@ enum Charset : char {
|
||||
MiddleDot = (char)149,
|
||||
AlmostEqual = (char)150,
|
||||
Degree = (char)151,
|
||||
Empty = (char)152 // This char is used to be parsed into EmptyExpression.
|
||||
Empty = (char)152, // This char is used to be parsed into EmptyExpression
|
||||
Superscript = (char)153 // This char is used to parse Power
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ Expression Parser::parseUntil(Token::Type stoppingType) {
|
||||
&Parser::parseUnexpected, // Token::EndOfStream
|
||||
&Parser::parseStore, // Token::Store
|
||||
&Parser::parseEqual, // Token::Equal
|
||||
&Parser::parseSuperscript, // Token::Superscript
|
||||
&Parser::parseUnexpected, // Token::RightBracket
|
||||
&Parser::parseUnexpected, // Token::RightParenthesis
|
||||
&Parser::parseUnexpected, // Token::RightBrace
|
||||
@@ -250,6 +251,23 @@ void Parser::parseStore(Expression & leftHandSide) {
|
||||
leftHandSide = Store(leftHandSide, static_cast<SymbolAbstract&>(rightHandSide));
|
||||
}
|
||||
|
||||
void Parser::parseSuperscript(Expression & leftHandSide) {
|
||||
if (leftHandSide.isUninitialized()) {
|
||||
m_status = Status::Error; // Power must have a left operand
|
||||
return;
|
||||
}
|
||||
Expression rightHandSide = parseUntil(Token::Superscript);
|
||||
if (m_status != Status::Progress) {
|
||||
return;
|
||||
}
|
||||
if (!popTokenIfType(Token::Superscript)) {
|
||||
m_status = Status::Error; // Right superscript marker missing.
|
||||
return;
|
||||
}
|
||||
leftHandSide = Power(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.
|
||||
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
void parseCaret(Expression & leftHandSide);
|
||||
void parseEqual(Expression & leftHandSide);
|
||||
void parseStore(Expression & leftHandSide);
|
||||
void parseSuperscript(Expression & leftHandSide);
|
||||
|
||||
// Parsing helpers
|
||||
bool parseBinaryOperator(const Expression & leftHandSide, Expression & rightHandSide, Token::Type stoppingType);
|
||||
|
||||
@@ -24,6 +24,9 @@ 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). */
|
||||
Superscript,
|
||||
/* Superscript marks the limit of a power. For instance:
|
||||
* 2 Superscript 3! Superscript ! is (2^(3!))! */
|
||||
RightBracket,
|
||||
RightParenthesis,
|
||||
RightBrace,
|
||||
|
||||
@@ -122,6 +122,12 @@ Token Tokenizer::popToken() {
|
||||
if (currentChar == Ion::Charset::MultiplicationSign || currentChar == Ion::Charset::MiddleDot) {
|
||||
return Token(Token::Times);
|
||||
}
|
||||
if (currentChar == '^') {
|
||||
return Token(Token::Caret);
|
||||
}
|
||||
if (currentChar == Ion::Charset::Superscript) {
|
||||
return Token(Token::Superscript);
|
||||
}
|
||||
if (currentChar == '!') {
|
||||
return Token(Token::Bang);
|
||||
}
|
||||
@@ -134,9 +140,6 @@ Token Tokenizer::popToken() {
|
||||
if (currentChar == ']') {
|
||||
return Token(Token::RightBracket);
|
||||
}
|
||||
if (currentChar == '^') {
|
||||
return Token(Token::Caret);
|
||||
}
|
||||
if (currentChar == '{') {
|
||||
return Token(Token::LeftBrace);
|
||||
}
|
||||
|
||||
@@ -174,20 +174,14 @@ int VerticalOffsetLayoutNode::serialize(char * buffer, int bufferSize, Preferenc
|
||||
return numberOfChar;
|
||||
}
|
||||
assert(m_type == Type::Superscript);
|
||||
// If the layout is a superscript, write "^(indice)"
|
||||
int numberOfChar = SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "^");
|
||||
// If the layout is a superscript, write "Ion::Charset::Superscript indice Ion::Charset::Superscript"
|
||||
int numberOfChar = SerializationHelper::Char(buffer, bufferSize, Ion::Charset::Superscript);
|
||||
if (numberOfChar >= bufferSize-1) { return bufferSize-1; }
|
||||
numberOfChar += const_cast<VerticalOffsetLayoutNode *>(this)->indiceLayout()->serialize(buffer+numberOfChar, bufferSize-numberOfChar, floatDisplayMode, numberOfSignificantDigits);
|
||||
if (numberOfChar >= bufferSize-1) { return bufferSize-1; }
|
||||
numberOfChar += SerializationHelper::Char(buffer+numberOfChar, bufferSize-numberOfChar, Ion::Charset::Superscript);
|
||||
if (numberOfChar >= bufferSize-1) { return bufferSize-1; }
|
||||
|
||||
// Add a multiplication if omitted.
|
||||
int indexInParent = -1;
|
||||
LayoutNode * parentNode = parent();
|
||||
if (parentNode != nullptr) {
|
||||
indexInParent = parentNode->indexOfChild(this);
|
||||
}
|
||||
if (indexInParent >= 0 && indexInParent < (parentNode->numberOfChildren() - 1) && parentNode->isHorizontal() && parentNode->childAtIndex(indexInParent + 1)->canBeOmittedMultiplicationRightFactor()) {
|
||||
buffer[numberOfChar++] = Ion::Charset::MiddleDot;
|
||||
if (numberOfChar >= bufferSize-1) { return bufferSize-1;}
|
||||
}
|
||||
buffer[numberOfChar] = 0;
|
||||
return numberOfChar;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user