From 7f085e8bf5f5bdf0cc2b8e39123db7bfa9a0742a Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 22 May 2012 22:10:57 +0000 Subject: Add some minimal support for precedence of operations git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4762 42af7a65-404d-4744-a932-0658087f49c3 --- NxWidgets/nxwm/include/chexcalculator.hxx | 59 +++++++++- NxWidgets/nxwm/src/chexcalculator.cxx | 181 ++++++++++++++++++++---------- 2 files changed, 176 insertions(+), 64 deletions(-) (limited to 'NxWidgets') diff --git a/NxWidgets/nxwm/include/chexcalculator.hxx b/NxWidgets/nxwm/include/chexcalculator.hxx index 3ac50f71c..9f9b61a9b 100644 --- a/NxWidgets/nxwm/include/chexcalculator.hxx +++ b/NxWidgets/nxwm/include/chexcalculator.hxx @@ -77,23 +77,63 @@ namespace NxWM private NXWidgets::CWidgetEventHandler { private: + /** + * The structure defines a pending operation. + */ + + struct SPendingOperation + { + int64_t value; /**< Accumulated value */ + uint8_t operation; /**< Identifies the operations */ + }; + + /** + * Calculator state data. + */ + + /** + * Cached constructor parameters. + */ + CTaskbar *m_taskbar; /**< Reference to the "parent" taskbar */ CApplicationWindow *m_window; /**< Reference to the application window */ + + /** + * Widgets + */ + NXWidgets::CButtonArray *m_keypad; /**< The calculator keyboard */ NXWidgets::CLabel *m_text; /**< The accumulator text display */ + + /** + * Calculator geometry. This stuff does not really have to be retained + * in memory. If you are pinched for memory, get rid of these. + */ + struct nxgl_size_s m_windowSize; /**< The size of the calculator window */ struct nxgl_size_s m_keypadSize; /**< The size the calculator keypad */ struct nxgl_size_s m_buttonSize; /**< The size of one calculator button */ struct nxgl_size_s m_textSize; /**< The size of the calculator textbox */ struct nxgl_point_s m_keypadPos; /**< The position the calculator keypad */ struct nxgl_point_s m_textPos; /**< The position of the calculator textbox */ - int64_t m_operand; /**< Previously entered operand */ + + /** + * Calculator computational data. Note: Since we do not support + * parentheses and support only two levels of operator precedence, it is + * not necessary to maintain a stack of operations. Within there + * limitations, there can be at most only one pending low prececence + * operation and one pending high precedence operation. If you want + * to support parentheses or more levels of precedence, they you will + * have to extend the design. + */ + int64_t m_accum; /**< The current accumulated value */ - int64_t m_memory; /**< The current value in memory */ - uint8_t m_pending; /**< The pending operation */ + int64_t m_memory; /**< The current value saved in memory */ + struct SPendingOperation m_low; /**< Low precedence pending operation */ + struct SPendingOperation m_high; /**< Hight precedence pending operation */ bool m_hexMode; /**< True if in hex mode */ - /** + /** * Select the geometry of the calculator given the current window size. * Only called as part of construction. */ @@ -113,6 +153,17 @@ namespace NxWM void labelKeypad(void); + /** + * Evaluate a binary operation. + * + * @param value1. The first value + * @param value2. The second value + * + * @return The result of the operation + */ + + int64_t evaluateBinaryOperation(uint8_t operation, int64_t value1, int64_t value2); + /** * Show the current value of the accumulator. */ diff --git a/NxWidgets/nxwm/src/chexcalculator.cxx b/NxWidgets/nxwm/src/chexcalculator.cxx index 48409f4d9..d865817b9 100644 --- a/NxWidgets/nxwm/src/chexcalculator.cxx +++ b/NxWidgets/nxwm/src/chexcalculator.cxx @@ -213,11 +213,13 @@ CHexCalculator::CHexCalculator(CTaskbar *taskbar, CApplicationWindow *window) // Reset other values - m_operand = 0; // No previously entered operand - m_accum = 0; // The accumulator is initially zero - m_memory = 0; // No value in memory - m_pending = (uint8_t)KEY_NONE; // No pending operation */ - m_hexMode = 0; // Decimal mode + m_accum = 0; // The accumulator is initially zero + m_memory = 0; // No value in memory + m_high.operation = (uint8_t)KEY_NONE; // No pending high precedence operation + m_high.value = 0; + m_low.operation = (uint8_t)KEY_NONE; // No pending high precedence operation + m_low.value = 0; + m_hexMode = 0; // Decimal mode // Add our personalized window label @@ -584,6 +586,55 @@ void CHexCalculator::labelKeypad(void) } } +/** + * Evaluate a binary operation. The result is left in m_accum. + * + * @param value1. The first value + * @param value2. The second value + * + * @return The result of the operation + */ + +int64_t CHexCalculator::evaluateBinaryOperation(uint8_t operation, int64_t value1, int64_t value2) +{ + switch (operation) + { + case KEY_NONE: // Do nothing if there is no pending operation + return 0; + + case KEY_XOR: // Exclusive OR + return value1 ^ value2; + + case KEY_DIVIDE: // Division + return value1 / value2; + + case KEY_RSH: // Right shift + return value1 >> value2; + + case KEY_LSH: // Left shift + return value1 << value2; + + case KEY_MULTIPLY: // Multiplication + return value1 * value2; + + case KEY_AND: // Bit-wise AND + return value1 & value2; + + case KEY_OR: // Bit-wise OR + return value1 | value2; + + case KEY_MINUS: // Subtraction + return value1 - value2; + + case KEY_PLUS: // Additions + return value1 + value2; + + default: + gdbg("ERROR: Unexpected pending operation %d\n", m_pending); + return 0; + } +} + /** * Show the current value of the accumulator. */ @@ -692,78 +743,86 @@ void CHexCalculator::handleActionEvent(const NXWidgets::CWidgetEventArgs &e) } break; - // Binary operators + // Low precedence Binary operators case KEY_XOR: // Exclusive OR - case KEY_DIVIDE: // Division - case KEY_RSH: // Right shift - case KEY_LSH: // Left shift - case KEY_MULTIPLY: // Multiplication - case KEY_AND: // Bit-wise AND case KEY_OR: // Bit-wise OR case KEY_MINUS: // Subtraction case KEY_PLUS: // Additions { - m_operand = m_accum; - m_accum = 0; - m_pending = g_keyDesc[index].keyType; + // Is there a high precedence operation? + + if (m_high.operation != (uint8_t)KEY_NONE) + { + m_accum = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum); + m_high.operation = (uint8_t)KEY_NONE; + m_high.value = 0; + } + + // Is there a pending low precedence operation? + + if (m_low.operation != (uint8_t)KEY_NONE) + { + m_accum = evaluateBinaryOperation(m_low.operation, m_low.value, m_accum); + } + + // Save the new low precedence operation + + m_low.operation = (uint8_t) g_keyDesc[index].keyType; + m_low.value = m_accum; + m_accum = 0; + updateText(); } break; - // Special operations - - case KEY_EQUAL: // Equal/Enter key - { - switch (m_pending) - { - case KEY_NONE: // Do nothing if there is no pending operation - return; + // High precedence Binary operators - case KEY_XOR: // Exclusive OR - m_accum ^= m_operand; - break; - - case KEY_DIVIDE: // Division - m_accum = m_operand / m_accum; - break; + case KEY_DIVIDE: // Division + case KEY_RSH: // Right shift + case KEY_LSH: // Left shift + case KEY_MULTIPLY: // Multiplication + case KEY_AND: // Bit-wise AND + { + // Is there a high precedence operation? - case KEY_RSH: // Right shift - m_accum = m_operand >> m_accum; - break; + if (m_high.operation != (uint8_t)KEY_NONE) + { + m_accum = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum); + } - case KEY_LSH: // Left shift - m_accum = m_operand << m_accum; - break; + // Save the new high precedence operation - case KEY_MULTIPLY: // Multiplication - m_accum *= m_operand; - break; + m_high.operation = (uint8_t) g_keyDesc[index].keyType; + m_high.value = m_accum; + m_accum = 0; - case KEY_AND: // Bit-wise AND - m_accum &= m_operand; - break; + updateText(); + } + break; - case KEY_OR: // Bit-wise OR - m_accum |= m_operand; - break; + // Special operations + + case KEY_EQUAL: // Equal/Enter key + { + // Is there a high precedence operation? - case KEY_MINUS: // Subtraction - m_accum = m_operand - m_accum; - break; + if (m_high.operation != (uint8_t)KEY_NONE) + { + m_accum = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum); + m_high.operation = (uint8_t)KEY_NONE; + m_high.value = 0; + } - case KEY_PLUS: // Additions - m_accum += m_operand; - break; + // Is there a pending low precedence operation? - default: - gdbg("ERROR: Unexpected pending operation %d\n", m_pending); - m_pending = KEY_NONE; - return; + if (m_low.operation != (uint8_t)KEY_NONE) + { + m_accum = evaluateBinaryOperation(m_low.operation, m_low.value, m_accum); + m_low.operation = (uint8_t)KEY_NONE; + m_low.value = 0; } - - m_operand = 0; - m_pending = KEY_NONE; + updateText(); } break; @@ -824,9 +883,11 @@ void CHexCalculator::handleActionEvent(const NXWidgets::CWidgetEventArgs &e) case KEY_CLR: // Clear all { - m_accum = 0; - m_operand = 0; - m_pending = KEY_NONE; + m_accum = 0; + m_high.operation = (uint8_t)KEY_NONE; + m_high.value = 0; + m_low.operation = (uint8_t)KEY_NONE; + m_low.value = 0; updateText(); } break; -- cgit v1.2.3