Thursday, March 18, 2010

Translator – Developmental Release (Compile Test)

There's a lot of different syntax being used that I never used before and I wanted to make sure it compiles before continuing. The Translator also uses lists of pointers, something that the test_stack program didn't actually test. With these lists, the items (in this case Tokens) are allocated elsewhere (the Parser), used by the Translator, and will eventually be deallocated by the Encoder.

I want to verify that list of pointers worked, so the test_stack was modified to test these kinds of lists, where the pointer values of the structures are output to verify everything was working correctly. Fortunately these pointer lists worked as expected, so no changes to the List class were necessary.

The Translator class was implemented in the main include file and the basic structure of the Translator's functions were implemented in a new source file. The add_token() doesn't actually process the tokens yet. Test Translator routines were added to the test_ibcp.cpp file. The goal was to make sure the basic structure would compile.  Trying to run the Translator with input mode will crash the program.

The ibcp_0.1.4-dev-1.zip file has been uploaded at Sourceforge IBCP Project along with the binary for the updated test_stack program (now moved to a test subdirectory). The ibcp.exe program doesn't do anything more than the last version except will print translator command line options, so it was not included in the binary .zip file.

Translator – Data Members

The Translator will have these data members:

    Table *table                                  – pointer to Table object
    List<Token *> *rpn_list                       – translated tokens list
    List<Token *> op_stack                        – pending operators stack
    List<List<Token *>::Element *> operand_stack  – processed operands stack

The members table, op_stack and operand_stack members will be initialized by argument or automatically by the constructor.  Upon calling the start() function, the rpn_list will be initialized (master item allocated).

Simple expressions have the general form of operand bin-op operand bin-op operand. Also each operand could be a lone operand or the form unary-op operand (where there may be more than one unary operator). The Translator will be either expecting an operand or unary operator(s) in front of the operand or a binary operator. Therefore, there will be a data member indicating what state the Translator is currently in along with it's enumeration definition:

    enum State:
        Initial   nothing processed yet
        BinOp    – expecting a binary operator
        Operand  – expecting a unary operator or operand
    State state  – current state of the translator

There may be states as more of the Translator is implemented. The state will be set to Initial by the start() function. Upon the first call to add_token(), the dummy Null token will be pushed to the op_stack and the state will be set to Operand to expect the first unary operator or operand.

Using The Translator

The Translator needs to be instanced, where there will be table argument pointer to the Table object, which will be needed by the Translator just like for the Parser.  The constructor will initialize the Translator's local Table point and will set it's RPN list pointer to a NULL. The input line is received from the user will be a C zero-terminated character array. This array needs to be initially fed to the Translator:

    Translator translator(table);
    char *input;
    . . .
    translator.start(input);

The start function will initialize internal variables and lists in preparation for translating the line into RPN format.  As Tokens are obtained from the parser, they will be fed to the Translator:

    Token *token;
    Translator::Status status;
    . . .
    do
    {
        token = parser.get_token();
        status = translator.add_token();
    }
    while (status == Translator::Good);

When the add_token() returns either a Done status or an error status, the loop will terminate.  If the status is Done, then the RPN list can be obtained from the Translator:

    List<Token *> *rpn_list = translator.get_result();

If the status is an error, the error will be reported. The token pointer will contain the part of the input line that contains the error (including it's starting column so the user can be informed where the error is).