From f8ed98b0ab354523031e3ab56b224f4f45827a42 Mon Sep 17 00:00:00 2001 From: hama Date: Thu, 3 Jul 2014 19:27:54 +0200 Subject: [PATCH] day's work --- rplexpr/rplasclasses.cpp | 64 ++++++++++++++++- rplexpr/rplasclasses.hpp | 11 +++ rplexpr/rplastree.cpp | 63 ++++++++++++++++- rplexpr/rplastree.hpp | 14 +++- rplexpr/rpllexer.cpp | 124 +++++++++++++++++---------------- rplexpr/rplmfparser.cpp | 19 ++++- rplexpr/rplmfparser.hpp | 7 +- rplexpr/rplsource.cpp | 23 ++++-- rplexpr/rplsource.hpp | 1 + unittests/rplmfparser_test.cpp | 4 +- 10 files changed, 251 insertions(+), 79 deletions(-) diff --git a/rplexpr/rplasclasses.cpp b/rplexpr/rplasclasses.cpp index 9edd340..3f24a0d 100644 --- a/rplexpr/rplasclasses.cpp +++ b/rplexpr/rplasclasses.cpp @@ -16,6 +16,7 @@ RplASFloat RplASFloat::m_instance; RplASInteger RplASInteger::m_instance; RplASString RplASString::m_instance; RplASBoolean RplASBoolean::m_instance; +RplASVoid RplASVoid::m_instance; /** @class RplSymbolSpace rplastree.hpp "rplexpr/rplastree.hpp" * @@ -64,6 +65,7 @@ RplSymbolSpace::RplSymbolSpace(RplSymbolSpace::SymbolSpaceType type, m_classes[RplASString::m_instance.name()] = &RplASString::m_instance; m_classes[RplASList::m_instance.name()] = &RplASList::m_instance; m_classes[RplASMap::m_instance.name()] = &RplASMap::m_instance; + m_classes[RplASVoid::m_instance.name()] = &RplASVoid::m_instance; } } @@ -126,7 +128,7 @@ void RplSymbolSpace::dump(FILE* fp, int indent, const char* header) QList::iterator it2; for (it2 = sorted.begin(); it2 != sorted.end(); it2++){ RplASClass* clazz = m_classes[*it2]; - clazz->dump(fp, indent + 1); + clazz->dump(fp, indent); } fprintf(fp, "%s== Variables:\n", tabs); @@ -140,11 +142,11 @@ void RplSymbolSpace::dump(FILE* fp, int indent, const char* header) QList::iterator it4; for (it4 = sorted.begin(); it4 != sorted.end(); it4++){ RplVariable* var = m_variables[*it4]; - var->dump(fp, indent + 1); + var->dump(fp, indent); } fprintf(fp, "%s== Body:%s\n", tabs, m_body == NULL ? " " : ""); if (m_body != NULL) - m_body->dump(fp, indent + 1); + m_body->dump(fp, indent); } /** @@ -710,3 +712,59 @@ void RplVariable::dump(FILE* fp, int indent) name1.constData(), name2.constData(), val.constData()); } + +/** @class RplVariable rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements a data type representing a none type. + */ +RplASVoid::RplASVoid() : + RplASClass("Void") +{ +} + +/** + * @brief Instantiates a new object. + * + * In this case we do nothing. + * + * @param source ignored + * @return + */ +void*RplASVoid::newValueInstance(void*) const +{ + return NULL; +} + +/** + * @brief Destroys an object created by newValueInstance. + * + * In this case we do nothing. + * + * @param object object to + * @return + */ +void RplASVoid::destroyValueInstance(void* object) const +{ +} + +/** + * @brief Returns the bool value of the given object + * @param object ignored + * @return false + */ +bool RplASVoid::boolValueOf(void*) const +{ + return false; +} + +/** + * @brief Converts the object into a string. + * + * @param object ignored + * @param maxLength ignored + * @return the empty string + */ +QString RplASVoid::toString(void*, int) const +{ + return QString(""); +} diff --git a/rplexpr/rplasclasses.hpp b/rplexpr/rplasclasses.hpp index 5b6481c..f4bf433 100644 --- a/rplexpr/rplasclasses.hpp +++ b/rplexpr/rplasclasses.hpp @@ -139,6 +139,17 @@ public: static RplASMap m_instance; }; +class RplASVoid : public RplASClass { +public: + RplASVoid(); +public: + void* newValueInstance(void* source = NULL) const; + void destroyValueInstance(void* object) const; + virtual bool boolValueOf(void* object) const; + virtual QString toString(void *object, int maxLength = 80) const; +public: + static RplASVoid m_instance; +}; #endif // RPLASCLASSES_HPP diff --git a/rplexpr/rplastree.cpp b/rplexpr/rplastree.cpp index 428304a..4972460 100644 --- a/rplexpr/rplastree.cpp +++ b/rplexpr/rplastree.cpp @@ -239,9 +239,9 @@ const QString* RplASVariant::asString() const { const RplASClass* clazz; const QString* rc = static_cast(asObject(&clazz)); - if (clazz->name() != "String"){ + if (clazz != &RplASString::m_instance){ const QString& name = clazz->name(); - throw RplException("RplASVariant::asString: not an string: %s", + throw RplException("RplASVariant::asString: not a string: %s", name.toUtf8().constData()); } return rc; @@ -568,6 +568,9 @@ void RplASVarDefinition::dump(FILE* fp, int indent) m_successor->dump(fp, indent); } +/** + * @brief Executes the statement. + */ void RplASVarDefinition::execute() { //@ToDo @@ -582,6 +585,57 @@ void RplASVarDefinition::calc(RplASVariant&) { } +/** @class RplASExprStatement rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements an statement consisting of an expression + */ + +/** + * @brief Constructor. + */ +RplASExprStatement::RplASExprStatement() : + RplASNode1(AST_EXPR_STATEMENT), + RplASStatement() +{ +} + +/** + * @brief Executes the statement. + */ +void RplASExprStatement::execute() +{ + +} + +/** + * @brief Calculates the value of the expression. + * + * @param value OUT: the calculated value + */ +void RplASExprStatement::calc(RplASVariant& value) +{ + +} + +/** + * @brief Writes the internals into a file. + * + * @param fp target file + * @param indent nesting level + */ + +void RplASExprStatement::dump(FILE* fp, int indent) +{ + DEFINE_TABS(indent); + fprintf(fp, "%sExpr id: %d succ: %d expr: %d\n", tabs, m_id, + m_successor == NULL ? 0 : m_successor->id(), + m_child == NULL ? 0 : m_child->id() ); + if (m_child != NULL) + m_child->dump(fp, indent + 1); + if (m_successor != NULL) + m_successor->dump(fp, indent); +} + /** @class RplASNode1 rplastree.hpp "rplexpr/rplastree.hpp" * * @brief Implements a inner node of the abstract syntax tree with one child. @@ -1214,6 +1268,9 @@ void RplASMethodCall::dump(FILE* fp, int indent) m_child->dump(fp, indent + 1); } +/** + * @brief Executes the statement. + */ void RplASMethodCall::execute() { } @@ -1344,7 +1401,7 @@ void RplASMethod::dump(FILE* fp, int indent) * @brief Implements an argument of a method for the Abstract Syntax Tree. */ /** - * @brief RplASArgument::RplASArgument + * @brief constructor */ RplASArgument::RplASArgument() : RplASNode2(AST_ARGUMENT), diff --git a/rplexpr/rplastree.hpp b/rplexpr/rplastree.hpp index 63b08a2..7c64dcc 100644 --- a/rplexpr/rplastree.hpp +++ b/rplexpr/rplastree.hpp @@ -15,6 +15,7 @@ enum RplASItemType { AST_CONSTANT, AST_NAMED_VALUE, AST_VAR_DEFINITION, + AST_EXPR_STATEMENT, AST_METHOD, AST_ARGUMENT, AST_INTRINSIC_METHOD, @@ -37,7 +38,8 @@ public: RplASException(); RplASException(const RplSourcePosition* position, const char* message, ...); protected: - void build(const RplSourcePosition* position, const char* format, va_list varList); + void build(const RplSourcePosition* position, const char* format, + va_list varList); }; class RplASClass; @@ -253,6 +255,16 @@ public: void dump(FILE* fp, int indent); }; +class RplASExprStatement : public RplASNode1, public RplASStatement +{ +public: + RplASExprStatement(); +public: + virtual void execute(); + virtual void calc(RplASVariant& value); + void dump(FILE* fp, int indent); +}; + class RplASUnaryOp : public RplASNode1 { public: diff --git a/rplexpr/rpllexer.cpp b/rplexpr/rpllexer.cpp index 82a0f8a..a13b011 100644 --- a/rplexpr/rpllexer.cpp +++ b/rplexpr/rpllexer.cpp @@ -845,73 +845,77 @@ RplToken* RplLexer::nextToken() ? &m_position2 : &m_position1; } else { m_currentToken->clear(); - m_currentPosition->setLineNo(m_source->currentReader() - ->currentSourceUnit()->lineNo()); - m_currentPosition->setColumn(m_currentCol); - if (! fillInput()){ + RplReader* reader = m_source->currentReader(); + if (reader == NULL) m_currentToken->m_tokenType = TOKEN_END_OF_SOURCE; - } else { - QChar cc = m_input.at(0); - int cc2 = cc.unicode(); - if (cc.isSpace()){ - m_currentToken->m_tokenType = TOKEN_SPACE; - ix = 1; - while(ix < m_input.size() && m_input.at(ix).isSpace()) - ix++; - if (m_storageFlags & STORE_BLANK){ - m_currentToken->m_string.append(m_input.mid(0, ix)); - } - m_currentCol += ix; - m_input.remove(0, ix); - rc = m_currentToken; - } else if (cc.isDigit()){ - rc = scanNumber(); - } else if ( (cc2 == '"' && (m_stringFeatures & SF_QUOTE) != 0) - || (cc2 == '\'' && (m_stringFeatures & SF_TICK) != 0)){ - rc = scanString(); + else { + m_currentPosition->setLineNo(reader->currentSourceUnit()->lineNo()); + m_currentPosition->setColumn(m_currentCol); + if (! fillInput()){ + m_currentToken->m_tokenType = TOKEN_END_OF_SOURCE; } else { - if (cc2 >= CHAR_INFO_SIZE) - throw RplLexException(*m_currentPosition, - "no lexical symbol can start with this char: %lc", - cc); - else - { - if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_COMMENT_START)){ - rc = findTokenWithId(TOKEN_COMMENT_START, - CC_2nd_COMMENT_START, m_commentStarts); - if (rc != NULL) - scanComment(); + QChar cc = m_input.at(0); + int cc2 = cc.unicode(); + if (cc.isSpace()){ + m_currentToken->m_tokenType = TOKEN_SPACE; + ix = 1; + while(ix < m_input.size() && m_input.at(ix).isSpace()) + ix++; + if (m_storageFlags & STORE_BLANK){ + m_currentToken->m_string.append(m_input.mid(0, ix)); } + m_currentCol += ix; + m_input.remove(0, ix); + rc = m_currentToken; + } else if (cc.isDigit()){ + rc = scanNumber(); + } else if ( (cc2 == '"' && (m_stringFeatures & SF_QUOTE) != 0) + || (cc2 == '\'' && (m_stringFeatures & SF_TICK) != 0)){ + rc = scanString(); + } else { + if (cc2 >= CHAR_INFO_SIZE) + throw RplLexException(*m_currentPosition, + "no lexical symbol can start with this char: %lc", + cc); + else + { + if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_COMMENT_START)){ + rc = findTokenWithId(TOKEN_COMMENT_START, + CC_2nd_COMMENT_START, m_commentStarts); + if (rc != NULL) + scanComment(); + } - if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_OP)){ - if ( (m_charInfo[cc2] & CC_OP_1_ONLY) == 0){ - rc = findTokenWithId(TOKEN_OPERATOR, - CC_2nd_OP, m_operators); - } else { + if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_OP)){ + if ( (m_charInfo[cc2] & CC_OP_1_ONLY) == 0){ + rc = findTokenWithId(TOKEN_OPERATOR, + CC_2nd_OP, m_operators); + } else { + rc = m_currentToken; + rc->m_tokenType = TOKEN_OPERATOR; + rc->m_value.m_id = findInVector(1, m_operators); + m_input.remove(0, 1); + m_currentCol += 1; + } + } + if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_KEYWORD)){ + rc = findTokenWithId(TOKEN_KEYWORD, + CC_2nd_KEYWORD, m_keywords); + } + if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_ID)){ + int length = 1; + while(length < m_input.size() + && (cc2 = m_input[length].unicode()) < CHAR_INFO_SIZE + && (m_charInfo[cc2] & CC_REST_ID) != 0) + length++; rc = m_currentToken; - rc->m_tokenType = TOKEN_OPERATOR; - rc->m_value.m_id = findInVector(1, m_operators); - m_input.remove(0, 1); - m_currentCol += 1; + rc->m_tokenType = TOKEN_ID; + rc->m_string.append(m_input.mid(0, length)); + m_input.remove(0, length); + m_currentCol += length; } - } - if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_KEYWORD)){ - rc = findTokenWithId(TOKEN_KEYWORD, - CC_2nd_KEYWORD, m_keywords); - } - if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_ID)){ - int length = 1; - while(length < m_input.size() - && (cc2 = m_input[length].unicode()) < CHAR_INFO_SIZE - && (m_charInfo[cc2] & CC_REST_ID) != 0) - length++; - rc = m_currentToken; - rc->m_tokenType = TOKEN_ID; - rc->m_string.append(m_input.mid(0, length)); - m_input.remove(0, length); - m_currentCol += length; - } + } } } } diff --git a/rplexpr/rplmfparser.cpp b/rplexpr/rplmfparser.cpp index f3a4203..bf2268d 100644 --- a/rplexpr/rplmfparser.cpp +++ b/rplexpr/rplmfparser.cpp @@ -318,6 +318,21 @@ RplASItem* RplMFParser::parseExpr() return rc; } +/** + * @brief Parses an expression as a statement. + * + * @return the abstract syntax tree of the expression statement + */ +RplASItem* RplMFParser::parseExprStatement() +{ + RplSourcePosition *pos = m_lexer.currentPosition(); + RplASItem* item = parseExpr(); + RplASExprStatement* statement = new RplASExprStatement(); + statement->setPosition(pos); + statement->setChild(item); + return statement; +} + /** * @brief Parses the body. * @@ -340,7 +355,7 @@ RplASItem* RplMFParser::parseBody() case TOKEN_REAL: case TOKEN_OPERATOR: m_lexer.undoLastToken(); - item = parseExpr(); + item = parseExprStatement(); break; case TOKEN_KEYWORD: switch (token->id()){ @@ -380,7 +395,7 @@ RplASItem* RplMFParser::parseBody() item = parseVarDefinition(K_UNDEF); } else { m_lexer.undoLastToken(); - item = parseExpr(); + item = parseExprStatement(); } break; } diff --git a/rplexpr/rplmfparser.hpp b/rplexpr/rplmfparser.hpp index c888be0..d0d7daa 100644 --- a/rplexpr/rplmfparser.hpp +++ b/rplexpr/rplmfparser.hpp @@ -17,14 +17,12 @@ public: K_UNDEF, K_IF, K_THEN, K_ELSE, K_FI, K_WHILE, K_DO, K_OD, K_REPEAT, K_UNTIL, K_FOR, K_FROM, K_TO, K_STEP, K_CASE, K_OF, K_ESAC, K_LEAVE, K_CONTINUE, K_PASS, K_CLASS, K_ENDC, K_ENDF, K_FUNCTION, K_GENERATOR, K_IMPORT, - K_CONST, K_LAZY, K_INT, K_FLOAT, K_BOOL, K_NONE, K_TRUE, K_FALSE + K_CONST, K_LAZY, K_NONE, K_TRUE, K_FALSE }; -#define IS_KEYWORD_BEHIND_EXPR(o) (o==K_THEN||o==K_DO||o==K_FROM||o==K_OF \ - ||o==K_ENDF||o==K_ENDC) #define MF_KEYWORDS "if then else fi while do od repeat until" \ " for from to step case of esac leave continue pass" \ " class endc endf func generator import" \ - " const lazy None True False" + " const lazy none true false" enum Operator { O_UNDEF, O_SEMI_SEMICOLON, O_SEMICOLON, O_COMMA, O_COLON, O_ASSIGN, O_PLUS_ASSIGN, O_MINUS_ASSIGN, O_DIV_ASSIGN, O_TIMES_ASSIGN, @@ -82,6 +80,7 @@ public: void parseImport(); RplASItem* parseModule(const QString& name); void parse(); + RplASItem*parseExprStatement(); protected: RplASArgument* parseArguments(); RplASItem* parseOperand(int level); diff --git a/rplexpr/rplsource.cpp b/rplexpr/rplsource.cpp index 850c63c..f7837de 100644 --- a/rplexpr/rplsource.cpp +++ b/rplexpr/rplsource.cpp @@ -240,12 +240,23 @@ RplReader::RplReader(RplSource& source) : /** * @brief Destructor. */ -RplReader::~RplReader() { +RplReader::~RplReader() +{ + clear(); +} + +/** + * @brief Frees the resources. + */ +void RplReader::clear() +{ QMap::iterator it; for(it = m_units.begin(); it != m_units.end(); it++) { RplStringSourceUnit* unit = (RplStringSourceUnit*)(*it); delete unit; } + m_units.clear(); + m_currentSourceUnit = NULL; } /** @@ -429,11 +440,11 @@ void RplSource::pushSourceUnit(RplSourceUnit* unit) { * otherwise: the last entry from the source unit stack */ RplSourceUnit* RplSource::popSourceUnit(RplReader* reader) { + RplSourceUnit* rc = NULL; if(m_unitStack.size() > 0) m_unitStack.pop(); m_currentReader = m_unitStack.size() <= 0 ? NULL : m_unitStack.top()->reader(); - RplSourceUnit* rc = NULL; if(m_currentReader == reader) rc = m_unitStack.top(); else { @@ -538,6 +549,7 @@ RplStringReader::RplStringReader(RplSource& source) : * @brief Destructor. */ RplStringReader::~RplStringReader() { + clear(); } /** @@ -569,8 +581,11 @@ RplSourceUnit* RplStringReader::openSourceUnit(const QString& unit) { */ bool RplStringReader::nextLine(int maxSize, QString& buffer, bool& hasMore) { - m_currentSourceUnit->setLineNo(m_currentSourceUnit->lineNo() + 1); - bool rc = fillBuffer(maxSize, buffer, hasMore); + bool rc = m_currentSourceUnit != NULL; + if (rc){ + m_currentSourceUnit->setLineNo(m_currentSourceUnit->lineNo() + 1); + rc = fillBuffer(maxSize, buffer, hasMore); + } return rc; } diff --git a/rplexpr/rplsource.hpp b/rplexpr/rplsource.hpp index e341f44..b9684b3 100644 --- a/rplexpr/rplsource.hpp +++ b/rplexpr/rplsource.hpp @@ -92,6 +92,7 @@ public: */ virtual bool fillBuffer(int maxSize, QString& buffer, bool& hasMore) = 0; public: + virtual void clear(); RplSource& source(); RplSourceUnit* currentSourceUnit() const; bool setCurrentSourceUnit(const QString& currentSourceUnit); diff --git a/unittests/rplmfparser_test.cpp b/unittests/rplmfparser_test.cpp index 6fe622e..011652a 100644 --- a/unittests/rplmfparser_test.cpp +++ b/unittests/rplmfparser_test.cpp @@ -22,14 +22,14 @@ public: m_tree(), m_reader(m_source) { - m_reader.addSource("", ""); m_source.addReader(&m_reader); } protected: void setSource(const char* content){ m_tree.clear(); m_source.clear(); - m_reader.replaceSource("", content); + m_reader.clear(); + m_reader.addSource("", content); m_source.addReader(&m_reader); m_source.addSourceUnit(m_reader.currentSourceUnit()); } -- 2.39.5