Saturday, November 2, 2013

Recreator – Simple Expressions

The recreator will work similar to the run-time module.  The run-time module will push operand values to a value stack to be popped by operators, functions and commands to perform some operation, which may push results back to the stack.  The recreator will push the strings of the operands to a string holding stack.  These strings will be popped by operators, functions and commands, which may push modified strings back to the stack or append the strings to the output string.  This will make more sense by considering this statement and its translation:
A + B
A B +
At the A operand, the string "A" will be pushed to the holding stack.  Same for the B operand with the "B" string being pushed.  The plus operator will pop the second operand, the "B" string, from the stack.  The string for the operator will be appended with surrounding spaces to the operand now on top of the stack, specifically the " + " string gets append to the "A" string leaving "A + " on top of the stack.  The previously popped second operand is then appended to the top of the stack leaving the "A + B" string on top of the stack, which may be an operand for the next operator.

For unary operators, the string for the operator is created.  A separator space is appended only for a word operator like NOT, otherwise no space is needed (for example the "-" unary operator).  The string of the single operand on top of the stack is popped and appended to the operator string.  The resulting string is pushed back to the stack.

For simple expressions, only support for operands (variables and constants) and operators are needed.  For string constants some processing is needed: all double quotes in the string of the constant need to be changed to two doubles quotes, and the entire string needs to be surrounded by a pair of double quotes.

The table entry for each code will have a pointer to a recreate function.  Since operands already have their string in the token of the item, this string just needs to be pushed to the string holding stack (with the exception of string constants).  Since this is trivial, a null pointer will indicate that the string of the token should be pushed to the string holding stack.  For string constants, there will be a constant string recreate function.  Since all binary operators work the same, there only needs to be a single binary operator recreate function.  Likewise for the unary operators.

The recreate process will loop through each item in the RPN list.  If there is no recreate function, the string of the token is pushed onto the string holding stack.  Otherwise the recreate function is called to process the token.  At the end of the RPN list, the resulting output string is returned.  For expression mode, nothing gets appended to the output list, so the tester class will need to pop the result string of the expression from the string holding stack.

Table – Simplified Instance Creation

The new recreator class will also require a reference to the single table instance like the other classes (parser, translator, and program model).  The initialization of the table reference members of these classes was not consistent - some required the table instance reference to be passed to the constructor and others accessed the static table instance directly to initialize their member.  The single table instance creation was also convoluted with several routines:
initialize - static table function to be called once (from main) to create the single instance and it made sure it was not called more than once or if the table entries had errors

has errors - static table function to return if the table has errors, used by the tester class to determine if the table entries had errors, outputs them and aborted the application

error list - static table function to return the list of error, used by the test class to output the table entry errors before aborting the application

setup and check - static table function called by initialize after creating the single table instance to setup and check the table entries

instance - static table function to return a reference to the single table instance, contains checks to make sure that initialize had been called and that the table entries had no errors; and for these errors would abort the application
The table constructor had an argument for the pointer to the table entry array and only set the table entry member.  Most of these routines were unnecessary and the single table instance creation was modified for these routines:
instance - static table function to return the single table instance, and will create the single table instance upon the first call

constructor - modified to take both the pointer to the table entry array and the count of table entries, now does the setup and check functionality, and if there are errors, they are reported and the application is aborted
Now if there are table entry errors, the constructor aborts the application and no other class needs to check for table errors.  This check was removed from the tester class.  Previously when starting in GUI mode, there was no check for table errors.  There is no longer a need to initialize the table in the main function or check to make sure it has been initialized.

The method the program model uses to initialize its table instance reference is the preferred method.  The instance function is used to initialize the table instance reference member.  The parser and translator classes were modified to use this method.

[commit 7a01ac428b]