- Post-Conditions:
- 1) If the Tokens array represented a correct C++ statement, according
to the constraints of requirements document §4.12, then that statement
will have been executed, and the appropriate changes will have occured
to the Node, Link, Line, Master Node, Master Link, and Master Line objects.
(No redraw will be called, hence these changes may not yet propogate to
the screen display.)
- 2) If the Tokens array represented a correct C++ boolean expression,
according to the constraints of requirements document §4.12, then
the value of that expression will be returned, and no changes will occur
to any other objects or to the screen display.
- 3) If the Tokens array do not represent a correct C++ statement or
boolean expression, then no changes will occur to any other objects or
to the screen display, and a "SyntaxErrorException" will be thrown.
|
- Algorithm:
- We read the tokens from the Tokens array one at a time (starting from
0), pushing them on a stack, or taking an action, depending on the token
we have just read. In the description below, the phrase "Verify"
means to check if something is true, to throw an exception if it is false,
and to continue processing if it is true. The phrase "Pop X"
means to pop the last token off the stack, verify (in the sense just described)
that it has TokenType X, and store it in a local variable "CurrentToken",
discarding any previous value there. The phrase "Pop into Operator"
means to pop the last token off the stack, but to place it into a second
local variable "Operator", leaving the value of "CurrentToken"
unchanged. The phrase "Read the next token" means to read the
current token from the Token array into "NewToken", and advance
the counter keeping track of the active location in the Token array.
- The main algorithm is a loop that runs through each token in the Token
array and takes the following action, depending on the TokenType of that
token:
- switch ( TokenType ) {
- On P, Q, R, S: Push a NODE_VALUE token where theNode is set
to p, q, r, or s respectively. Set NodeField to 'R'.
- On ARROW: Pop a NODE_VALUE token. Verify that NodeField is 'R'
or 'L'. Ask theNode for its Next or Prev node (as appropriate).
Verify this is a legal node (depends on how Node object ends up handling
these calls for invalid pointers). Put that Node into theNode, set
NodeField to '?', and push this token.
- On NEXT, PREV, DATA: Pop a NODE_VALUE token. Verify that NodeField
is '?'. Set NodeField to 'R' for NEXT, 'L' for PREV, or 'D' for
DATA. Push the token.
- On IF, NEW, DELETE, NULL, LEFT_PAREN, ASSIGN, EQUAL, NOT_EQUAL, GREATER,
LESS, GREATER_EQUAL, LESS_EQUAL, AND, OR, NOT, NUMBER_LITERAL, STRING_LITERAL:
Push the token.
- // If we added "BOOLEAN_LITERAL" to acceptable inputs, it
would go here also.
- On INT_NODE, STR_NODE: Push the token. Read the next token. Verify
it is a SEMI_COLON. Verify we're at the end of the TokenArray. Pop the
(INT_NODE, STR_NODE) token. Pop NEW. Pop ASSIGN. Pop NODE_VALUE. Verify
the stack is empty. Call MasterNodeObject.NewNode( CurrentToken.theNode
). Use the return value from this call for either CurrentToken.theNode.SetNext()
or SetPrev() as appropriate.
- On RIGHT_PAREN:
- LOOP: Pop either a NODE_VALUE token or one of the LITERAL tokens (including
"NULL"). Pop into "Operator". The next step depends
on the type of this operator:
- switch (Operator.TokenType) {
- LEFT_PAREN: Push the CurrentToken. Done processing (break).
- NOT: Verify the CurrentToken is BOOLEAN_LITERAL, invert its literal
value, and push it.
- AND, OR: Verify CurrentToken is BOOLEAN_LITERAL. Pop BOOLEAN_LITERAL.
Calculate new literal value and Push it.
- GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL:
- Pop into another local variable either a NODE_VALUE token or one of
the LITERAL tokens. Verify that the type of this token is compatible with
the one in CurrentToken. Calculate the value of this boolean expression,
calling such methods as Node.GetNext(), Node.GetPrev(), and Node.GetData()
to get the actual values of the left and right sides of the operand. Push
the resulting boolean literal.
- ASSIGN: Throw IllegalAssignmentException. (Should be caught by the
Parser?)
- Otherwise: Throw SyntaxErrorException.
- }
- Except for those two cases that were indicated as "Done processing",
we should continue looping on this case, as implied above. When
done, check the stack size. If only one item on it, we are evaluating
a boolean expression, so return the appropriate value. If the
stack size is 1, Pop an IF token, then call ThenStatement.Execute()
or ElseStatement.Execute() as appropriate.
- On SEMI_COLON: Verify we're at the last token in Tokens. Pop into "Operator".
The next step depends on the type of this operator:
- switch (Operator.TokenType) {
- DELETE: Call MasterNode.DeleteNode(). Somehow find a way to set all
pointers that used to point to this node to "Uninitialized" values.
- ASSIGN: Pop into another local variable a NODE_VALUE token. Verify
that the type of this token is compatible with the one in CurrentToken.
If CurrentToken is a NODE_VALUE, use Node.GetNext(), Node.GetPrev(), or
Node.GetData() to get the actual value to assign, otherwise, use the Literal.
Use Node.SetNext(), Node.SetPrev(), or Node.SetData() to update the data
for the newly popped NODE_VALUE. Call the appropriate DeleteLink() and
MakeLink() routines to erase any previous lnk n ocrae e new ones.
- }
|