From a88ed2f2bb7a36d321055d6058f24ff70a1f1157 Mon Sep 17 00:00:00 2001 From: Thunder422 Date: Fri, 9 Nov 2012 23:52:39 -0500 Subject: [PATCH] changed how parser is called; added new translate function instead of creating a single parser instance for the whole program (in main), a parser instance is created when needed (since there are no member variables that need to be kept between parse calls implemented a new translator function setInput() to translate a line and return the status of the translate; if successful then the rpn output list can be obtained, otherwise the error can be obtained; this function instances its own parser to parse the input test routine parseInput() rewritten to instance its own parser test routine translateInput() rewritten to use new Translator setInput() function along with new functions for returning error token and message --- ibcp.cpp | 7 +++--- test_ibcp.cpp | 64 +++++++++++++------------------------------------ token.h | 4 +++- translator.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ translator.h | 51 ++++++++++++++++++++++++--------------- 5 files changed, 119 insertions(+), 72 deletions(-) diff --git a/ibcp.cpp b/ibcp.cpp index 449cb77..33e783f 100644 --- a/ibcp.cpp +++ b/ibcp.cpp @@ -151,8 +151,8 @@ bool ibcpVersion(QTextStream &cout, const QString &name, int argc, char *argv[]) // prototype for test function -bool ibcpTest(QTextStream &cout, Translator &translator, Parser &parser, - int argc, char *argv[]); +bool ibcpTest(QTextStream &cout, Translator &translator, int argc, + char *argv[]); int main(int argc, char *argv[]) @@ -187,9 +187,8 @@ int main(int argc, char *argv[]) cout << "Table initialization successful." << endl; Translator translator(Table::instance()); - Parser parser(Table::instance()); - if (!ibcpTest(cout, translator, parser, argc, argv)) + if (!ibcpTest(cout, translator, argc, argv)) { qWarning("usage: %s -v -t |-tp|-te|-tt", qPrintable(programName)); diff --git a/test_ibcp.cpp b/test_ibcp.cpp index 6998a54..49ca69c 100644 --- a/test_ibcp.cpp +++ b/test_ibcp.cpp @@ -212,8 +212,8 @@ #include "parser.h" #include "translator.h" -void parseInput(QTextStream &cout, Parser &parser, const QString &testInput); -void translateInput(QTextStream &cout, Translator &translator, Parser &parser, +void parseInput(QTextStream &cout, const QString &testInput); +void translateInput(QTextStream &cout, Translator &translator, const QString &testInput, bool exprMode); bool printToken(QTextStream &cout, Token *token, bool tab); void printOutput(QTextStream &cout, const QString &header, @@ -224,8 +224,7 @@ void printError(QTextStream &cout, Token *token, const QString &error); // function to process a test input file specified on the command line // or accept input lines from the user -bool ibcpTest(QTextStream &cout, Translator &translator, Parser &parser, - int argc, char *argv[]) +bool ibcpTest(QTextStream &cout, Translator &translator, int argc, char *argv[]) { extern char *programName; @@ -332,13 +331,13 @@ bool ibcpTest(QTextStream &cout, Translator &translator, Parser &parser, switch (testMode) { case testParser: - parseInput(cout, parser, inputLine); + parseInput(cout, inputLine); break; case testExpression: - translateInput(cout, translator, parser, inputLine, true); + translateInput(cout, translator, inputLine, true); break; case testTranslator: - translateInput(cout, translator, parser, inputLine, false); + translateInput(cout, translator, inputLine, false); break; } } @@ -355,8 +354,9 @@ bool ibcpTest(QTextStream &cout, Translator &translator, Parser &parser, // function to parse an input line and print the resulting tokens -void parseInput(QTextStream &cout, Parser &parser, const QString &testInput) +void parseInput(QTextStream &cout, const QString &testInput) { + Parser parser(Table::instance()); Token *token; bool more; @@ -378,33 +378,12 @@ void parseInput(QTextStream &cout, Parser &parser, const QString &testInput) // function to parse an input line, translate to an RPN list // and output the resulting RPN list -void translateInput(QTextStream &cout, Translator &translator, Parser &parser, +void translateInput(QTextStream &cout, Translator &translator, const QString &testInput, bool exprMode) { - Token *token; - Token *orgToken; - TokenStatus status; - - translator.start(exprMode); - parser.setInput(QString(testInput)); - do { - // set parser operand state from translator - parser.setOperandState(translator.getOperandState()); - orgToken = token = parser.getToken(); - if (token->isType(Error_TokenType)) - { - printError(cout, token, token->string()); - delete token; - translator.cleanUp(); - return; - } - //printToken(cout, token, tab); - status = translator.addToken(token); - } - while (status == Good_TokenStatus); - if (status == Done_TokenStatus) + if (translator.setInput(testInput, exprMode)) { - QList *rpnList = translator.getResult(); + QList *rpnList = translator.output(); printOutput(cout, "Output", *rpnList); while (!rpnList->isEmpty()) { @@ -412,25 +391,14 @@ void translateInput(QTextStream &cout, Translator &translator, Parser &parser, } delete rpnList; } - else // error occurred, output it + else // translate error occurred { - // token pointer is set to cause of error - printError(cout, token, QString(token->message(status))); - if (token == orgToken) - { - // only deleted error token if it's the original token - // returned from the parser, if not then this token is - // in the output list and will be deleted by the - // clean_up() function (the original token has been - // already been deleted by the Translator) XXX - delete token; - } - else // check if token is open paren + Token *token = translator.errorToken(); + printError(cout, token, translator.errorMessage()); + if (!token->isType(Error_TokenType)) { - translator.deleteOpenParen(token); + cout << endl; // FIXME not needed, here to match current results } - translator.cleanUp(); - cout << endl; // FIXME not needed, here to match current results } } diff --git a/token.h b/token.h index 3d4654a..68af862 100644 --- a/token.h +++ b/token.h @@ -70,9 +70,11 @@ class Token { m_reference = false; m_subCode = None_SubCode; } - ~Token(void) + Token(const Token &token) // copy constructor { + *this = token; } + ~Token(void) {} // column and length access functions int column(void) diff --git a/translator.cpp b/translator.cpp index 424382f..ed0a8c0 100644 --- a/translator.cpp +++ b/translator.cpp @@ -374,7 +374,9 @@ // 2012-11-01 removed immediate command support #include "translator.h" +#include "token.h" #include "table.h" +#include "parser.h" #include "tokenhandlers.h" @@ -490,6 +492,69 @@ TokenStatus Translator::variableErrStatus(DataType dataType) } +// function to parse and translate an input line to an RPN output list +// +// - returns true if successful, use output() to get RPN output list +// - returns false if failed, use errorToken() and errorMessage() +// to get token error occurred at and the error message + +bool Translator::setInput(const QString &input, bool exprMode) +{ + Token *token; + Token *parsedToken; + TokenStatus status; + + Parser parser(m_table); + parser.setInput(input); + + m_exprMode = exprMode; // save flag + // (expression mode for testing) + m_mode = m_exprMode ? Expression_TokenMode : Command_TokenMode; + + m_output = new QList; + m_state = Initial_State; + + do { + // set parser operand state from translator + parser.setOperandState(m_state == Operand_State + || m_state == OperandOrEnd_State); + token = parsedToken = parser.getToken(); + if (token->isType(Error_TokenType)) + { + setErrorToken(token); + // XXX determine error code from what's expected next + m_errorMessage = token->string(); + cleanUp(); + return false; + } + status = addToken(token); + } + while (status == Good_TokenStatus); + + if (status != Done_TokenStatus) + { + // token pointer is set to cause of error + // check if token is the parsed token or is an open paren + if (token == parsedToken || token->hasTableEntry() + && token->isCode(OpenParen_Code)) + { + // token is not already in the output list + setErrorToken(token); + } + else // token is in the rpn output list + { + // make a copy of the token to save + setErrorToken(new Token(*token)); + } + m_errorMessage = token->message(status); + cleanUp(); + return false; + } + // TODO check if stacks are empty + return true; +} + + // function to add a token to the output list, but token may be placed // on hold stack pending adding it to the output list so that higher // precedence tokens may be added to the list first diff --git a/translator.h b/translator.h index 307aa62..df759e5 100644 --- a/translator.h +++ b/translator.h @@ -165,31 +165,35 @@ class Translator { TokenMode m_mode; // current assignment mode QStack m_cmdStack; // stack of commands waiting processing bool m_exprMode; // expression only mode active flag + Token *m_errorToken; // token when error occurred + QString m_errorMessage; // message of error that occurred public: Translator(Table &table): m_table(table), m_output(NULL), - m_pendingParen(NULL) {} - void start(bool exprMode = false) + m_pendingParen(NULL), m_errorToken(NULL) {} + ~Translator(void) { - m_exprMode = exprMode; // save flag - m_output = new QList; - m_state = Initial_State; - // (expression mode for testing) - m_mode = m_exprMode ? Expression_TokenMode : Command_TokenMode; - } - // function to access if operand state - bool getOperandState(void) - { - return m_state == Operand_State || m_state == OperandOrEnd_State; + if (m_errorToken != NULL) + { + delete m_errorToken; + } } - TokenStatus addToken(Token *&token); - QList *getResult(void) // only call when add_token returns Done + + bool setInput(const QString &input, bool exprMode = false); + QList *output(void) // only call when setInput() returns true { QList *list = m_output; m_output = NULL; return list; } - void cleanUp(void); // only call when add_token returns an error + Token *errorToken(void) // only call when setInput() returns false + { + return m_errorToken; + } + QString errorMessage(void) // only call when setInput() returns false + { + return m_errorMessage; + } private: enum Match { @@ -199,6 +203,7 @@ class Translator { sizeof_Match }; + TokenStatus addToken(Token *&token); TokenStatus processOperand(Token *&token); TokenStatus endExpressionError(void); bool processUnaryOperator(Token *&token, TokenStatus &status); @@ -214,8 +219,10 @@ class Translator { TokenStatus expressionEnd(void); TokenStatus parenStatus(void); TokenStatus getExprDataType(DataType &dataType); + void deleteOpenParen(Token *token); void deleteCloseParen(Token *token); TokenStatus callCommandHandler(Token *&token); + void cleanUp(void); // only call when addToken() returns error // COMMAND SPECIFIC FUNCTIONS TokenStatus addPrintCode(void); @@ -228,11 +235,17 @@ class Translator { static TokenStatus variableErrStatus(DataType dataType); static DataType equivalentDataType(DataType dataType); -public: - // function to delete an open paren token - // (public to be used to delete token to prevent memory leak) - void deleteOpenParen(Token *token); + // set error token (deleting any previous error token first) + void setErrorToken(Token *errorToken) + { + if (m_errorToken != NULL) + { + delete m_errorToken; + } + m_errorToken = errorToken; + } +public: // token handler friend function definitions section friend TokenStatus Operator_Handler(Translator &t, Token *&token); friend TokenStatus Equal_Handler(Translator &t, Token *&token);