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
This commit is contained in:
parent
8a19aea00b
commit
0c093cee78
@ -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.
|
||||
*/
|
||||
|
@ -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,21 +743,60 @@ void CHexCalculator::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
|
||||
}
|
||||
break;
|
||||
|
||||
// Binary operators
|
||||
// Low precedence Binary operators
|
||||
|
||||
case KEY_XOR: // Exclusive OR
|
||||
case KEY_OR: // Bit-wise OR
|
||||
case KEY_MINUS: // Subtraction
|
||||
case KEY_PLUS: // Additions
|
||||
{
|
||||
// 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;
|
||||
|
||||
// High precedence Binary operators
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Save the new high precedence operation
|
||||
|
||||
m_high.operation = (uint8_t) g_keyDesc[index].keyType;
|
||||
m_high.value = m_accum;
|
||||
m_accum = 0;
|
||||
|
||||
updateText();
|
||||
}
|
||||
break;
|
||||
@ -715,55 +805,24 @@ void CHexCalculator::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
|
||||
|
||||
case KEY_EQUAL: // Equal/Enter key
|
||||
{
|
||||
switch (m_pending)
|
||||
// Is there a high precedence operation?
|
||||
|
||||
if (m_high.operation != (uint8_t)KEY_NONE)
|
||||
{
|
||||
case KEY_NONE: // Do nothing if there is no pending operation
|
||||
return;
|
||||
|
||||
case KEY_XOR: // Exclusive OR
|
||||
m_accum ^= m_operand;
|
||||
break;
|
||||
|
||||
case KEY_DIVIDE: // Division
|
||||
m_accum = m_operand / m_accum;
|
||||
break;
|
||||
|
||||
case KEY_RSH: // Right shift
|
||||
m_accum = m_operand >> m_accum;
|
||||
break;
|
||||
|
||||
case KEY_LSH: // Left shift
|
||||
m_accum = m_operand << m_accum;
|
||||
break;
|
||||
|
||||
case KEY_MULTIPLY: // Multiplication
|
||||
m_accum *= m_operand;
|
||||
break;
|
||||
|
||||
case KEY_AND: // Bit-wise AND
|
||||
m_accum &= m_operand;
|
||||
break;
|
||||
|
||||
case KEY_OR: // Bit-wise OR
|
||||
m_accum |= m_operand;
|
||||
break;
|
||||
|
||||
case KEY_MINUS: // Subtraction
|
||||
m_accum = m_operand - m_accum;
|
||||
break;
|
||||
|
||||
case KEY_PLUS: // Additions
|
||||
m_accum += m_operand;
|
||||
break;
|
||||
|
||||
default:
|
||||
gdbg("ERROR: Unexpected pending operation %d\n", m_pending);
|
||||
m_pending = KEY_NONE;
|
||||
return;
|
||||
m_accum = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum);
|
||||
m_high.operation = (uint8_t)KEY_NONE;
|
||||
m_high.value = 0;
|
||||
}
|
||||
|
||||
m_operand = 0;
|
||||
m_pending = KEY_NONE;
|
||||
|
||||
// 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);
|
||||
m_low.operation = (uint8_t)KEY_NONE;
|
||||
m_low.value = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user