From: hama Date: Sun, 6 Jul 2014 16:11:56 +0000 (+0200) Subject: day's work X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=6648e622159f38f349d3f5d2ee5e9e52e2b2ea82;p=reqt day's work --- diff --git a/rplcore/rpltest.cpp b/rplcore/rpltest.cpp index d68bfee..3440f71 100644 --- a/rplcore/rpltest.cpp +++ b/rplcore/rpltest.cpp @@ -352,14 +352,14 @@ bool RplTest::assertEqualFiles(const char* expected, const char* current, snprintf(buffer, sizeof buffer, "%s has no content. Does it exist?", expected); error(buffer); - } else if (expectedContent.isEmpty()){ + } else if (currentContent.isEmpty()){ char buffer[512]; snprintf(buffer, sizeof buffer, "%s has no content. Does it exist?", current); error(buffer); } else { QList expLines = expectedContent.split('\n'); - QList curLines = expectedContent.split('\n'); + QList curLines = currentContent.split('\n'); rc = assertEquals(expLines, curLines, file, lineNo); } return rc; diff --git a/rplexpr/rplastree.cpp b/rplexpr/rplastree.cpp index 827ce7e..b6f6c5f 100644 --- a/rplexpr/rplastree.cpp +++ b/rplexpr/rplastree.cpp @@ -397,6 +397,21 @@ unsigned int RplASItem::id() const return m_id; } +/** + * @brief Returns the position as a string. + * + * @param buffer OUT: the target buffer + * @param bufferSize size of the target buffer + * @return buffer + */ +char* RplASItem::positionStr(char buffer[], size_t bufferSize) const +{ + char* rc = (char*) ""; + if (m_position != NULL) + rc = m_position->utf8(buffer, bufferSize); + return rc; +} + /** * @brief Resets the static id counter. */ @@ -404,7 +419,15 @@ void RplASItem::reset() { m_nextId = 1; } - +/** + * @brief Returns the node type. + * + * @return the node type + */ +RplASItemType RplASItem::nodeType() const +{ + return m_nodeType; +} /** @class RplASExpr rplastree.hpp "rplexpr/rplastree.hpp" * @@ -453,7 +476,7 @@ void RplASConstant::dump(FILE* fp, int indent) char buffer[256]; fprintf(fp, "%sconst id: %d value: %s %s\n", tabs, m_id, m_value.toString().toUtf8().constData(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); } /** @@ -537,7 +560,7 @@ void RplASNamedValue::dump(FILE* fp, int indent) char buffer[256]; fprintf(fp, "%snamedValue %s id: %d attr: 0x%x %s\n", tabs, m_name.toUtf8().constData(), m_id, m_attributes, - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); } /** @class RplVarDefinition rplastree.hpp "rplexpr/rplastree.hpp" @@ -574,7 +597,7 @@ void RplASVarDefinition::dump(FILE* fp, int indent) fprintf(fp, "%svarDef %s (%s) id: %d succ: %d attr: 0x%x %s\n", tabs, name.constData(), className.constData(), m_id, m_successor == NULL ? 0 : m_successor->id(), m_attributes, - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (m_child != NULL) m_child->dump(fp, indent + 1); if (m_successor != NULL) @@ -643,7 +666,7 @@ void RplASExprStatement::dump(FILE* fp, int indent) fprintf(fp, "%sExpr id: %d succ: %d expr: %d %s\n", tabs, m_id, m_successor == NULL ? 0 : m_successor->id(), m_child == NULL ? 0 : m_child->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (m_child != NULL) m_child->dump(fp, indent + 1); if (m_successor != NULL) @@ -680,9 +703,9 @@ RplASNode1::~RplASNode1() * * @return the child of the instance */ -RplASItem*RplASNode1::child() const +RplASItem* RplASNode1::child() const { - + return m_child; } /** * @brief Sets the child. @@ -903,9 +926,12 @@ void RplASUnaryOp::dump(FILE* fp, int indent) { DEFINE_TABS(indent); char buffer[256]; - fprintf(fp, "%sUnary %d op: %d Child: %d %s\n", tabs, m_id, m_operator, + fprintf(fp, "%sUnary %d op: %s (%d) Child: %d %s\n", tabs, + m_id, + RplLexer::m_active->nameOfOp(m_operator).constData(), + m_operator, m_child == NULL ? 0 : m_child->id(), - m_position->utf8(buffer, sizeof buffer) ); + positionStr(buffer, sizeof buffer) ); if (m_child != NULL) m_child->dump(fp, indent); } @@ -1018,7 +1044,7 @@ void RplASCondition::dump(FILE* fp, int indent) char buffer[256]; fprintf(fp, "%sCondition %d Child: %d %s\n", tabs, m_id, m_child == NULL ? 0 : m_child->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (m_child != NULL) m_child->dump(fp, indent); } @@ -1079,7 +1105,7 @@ void RplASIf::dump(FILE* fp, int indent) fprintf(fp, "%sIf id: %d condition: %d then: %d else: %d %s\n", tabs, m_id, m_child->id(), m_child2->id(), m_child3 == NULL ? 0 : m_child3->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); m_child->dump(fp, indent + 1); m_child2->dump(fp, indent + 1); if (m_child3 != NULL) @@ -1099,11 +1125,14 @@ void RplASIf::dump(FILE* fp, int indent) /** * @brief Constructor. + * + * @param variable NULL or the iterator variable */ -RplASFor::RplASFor() : - RplASNode4(AST_FOR), +RplASForIterated::RplASForIterated(RplASNamedValue* variable) : + RplASNode3(AST_ITERATED_FOR), RplASStatement() { + m_child2 = variable; } /** @@ -1115,25 +1144,8 @@ RplASFor::RplASFor() : * m_child3: forwarding statement * m_child4: body */ -void RplASFor::execute() +void RplASForIterated::execute() { - ((RplASStatement*) m_child)->execute(); - RplASCondition* condition = dynamic_cast(m_child2); - if (condition == NULL) - throw RplASException(m_child2 == NULL ? m_position : m_child2->position(), - "for statement: not a condition"); - RplASStatement* forwarding = dynamic_cast(m_child3); - if (forwarding == NULL) - throw RplASException(m_child3 == NULL ? m_position : m_child3->position(), - "for statement: forwarding is not a statement"); - RplASStatement* body = dynamic_cast(m_child4); - if (body == NULL) - throw RplASException(m_child4 == NULL ? m_position : m_child4->position(), - "for statement: body is not a statement"); - while(condition->calcAsBool()){ - body->execute(); - forwarding->execute(); - } } /** @@ -1142,18 +1154,22 @@ void RplASFor::execute() * @param fp target file * @param indent nesting level */ -void RplASFor::dump(FILE* fp, int indent) +void RplASForIterated::dump(FILE* fp, int indent) { DEFINE_TABS(indent); char buffer[256]; - fprintf(fp, "%sfor id: %d condition: %d then: %d else: %d %s\n", tabs, - m_id, m_child->id(), m_child2->id(), + fprintf(fp, "%sforIt id: %d var: %d set: %d body: %d %s\n", tabs, + m_id, + m_child2 == NULL ? 0 : m_child2->id(), m_child3 == NULL ? 0 : m_child3->id(), - m_position->utf8(buffer, sizeof buffer)); - m_child->dump(fp, indent + 1); - m_child2->dump(fp, indent + 1); + m_child == NULL ? 0 : m_child->id(), + positionStr(buffer, sizeof buffer)); + if (m_child2 != NULL) + m_child2->dump(fp, indent + 1); if (m_child3 != NULL) m_child3->dump(fp, indent + 1); + if (m_child != NULL) + m_child->dump(fp, indent + 1); } /** @class RplASForCounted rplastree.hpp "rplexpr/rplastree.hpp" @@ -1169,11 +1185,14 @@ void RplASFor::dump(FILE* fp, int indent) /** * @brief Constructor. + * + * @param variable NULL or the counter variable */ -RplASForCounted::RplASForCounted() : - RplASNode5(AST_FOR), +RplASForCounted::RplASForCounted(RplASNamedValue* variable) : + RplASNode5(AST_ITERATED_FOR), RplASStatement() { + m_child2 = variable; } /** @@ -1221,7 +1240,7 @@ void RplASForCounted::dump(FILE* fp, int indent) m_child4 == NULL ? 0 : m_child4->id(), m_child5 == NULL ? 0 : m_child5->id(), m_child == NULL ? 0 : m_child->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (m_child2 != NULL) m_child2->dump(fp, indent + 1); if (m_child3 != NULL) @@ -1283,7 +1302,7 @@ void RplASWhile::dump(FILE* fp, int indent) fprintf(fp, "%swhile id: %d condition: %d body: %d %s\n", tabs, m_id, m_child2 == NULL ? 0 : m_child2->id(), m_child == NULL ? 0 : m_child->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (m_child2 != NULL) m_child2->dump(fp, indent + 1); if (m_child != NULL) @@ -1339,11 +1358,11 @@ void RplASRepeat::dump(FILE* fp, int indent) fprintf(fp, "%srepeat id: %d condition: %d body: %d %s\n", tabs, m_id, m_child2 == NULL ? 0 : m_child2->id(), m_child == NULL ? 0 : m_child->id(), - m_position->utf8(buffer, sizeof buffer)); - if (m_child2 != NULL) - m_child2->dump(fp, indent + 1); + positionStr(buffer, sizeof buffer)); if (m_child != NULL) m_child->dump(fp, indent + 1); + if (m_child2 != NULL) + m_child2->dump(fp, indent + 1); } /** @class RplASClass rplastree.hpp "rplexpr/rplastree.hpp" @@ -1628,7 +1647,7 @@ void RplASMethodCall::dump(FILE* fp, int indent) fprintf(fp, "%sCall %d instance: %d args: %d %s\n", tabs, m_id, m_child == NULL ? 0 : m_child->id(), m_child2 == NULL ? 0 : m_child2->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (m_child != NULL) m_child->dump(fp, indent + 1); if (m_child2 != NULL) @@ -1724,7 +1743,7 @@ void RplASBinaryOp::dump(FILE* fp, int indent) opName.constData(), m_operator, m_child == NULL ? 0 : m_child->id(), m_child2 == NULL ? 0 : m_child2->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); if (indent < 32 && m_child != NULL) m_child->dump(fp, indent + 1); if (indent < 32 && m_child2 != NULL) @@ -1765,7 +1784,7 @@ void RplASMethod::dump(FILE* fp, int indent) m_name.toUtf8().constData()); fprintf(fp, ") body: %d args: %d %s\n", m_child == NULL ? 0 : m_child->id(), m_child2 == NULL ? 0 : m_child2->id(), - m_position->utf8(buffer, sizeof buffer)); + positionStr(buffer, sizeof buffer)); } /** @class RplASArgument rplastree.hpp "rplexpr/rplastree.hpp" diff --git a/rplexpr/rplastree.hpp b/rplexpr/rplastree.hpp index cf0a566..9d9d825 100644 --- a/rplexpr/rplastree.hpp +++ b/rplexpr/rplastree.hpp @@ -27,7 +27,7 @@ enum RplASItemType { AST_REPEAT, AST_IF, AST_CONDITION, - AST_FOR, + AST_ITERATED_FOR, AST_COUNTED_FOR, AST_SWITCH, AST_LEAVE, @@ -119,6 +119,7 @@ public: const RplSourcePosition* position() const; void setPosition(const RplSourcePosition* position); unsigned int id() const; + char* positionStr(char buffer[], size_t bufferSize) const; public: /** * @brief Writes the content of the instance into a file. @@ -130,6 +131,8 @@ public: virtual void dump(FILE* fp, int indent) = 0; public: static void reset(); + RplASItemType nodeType() const; + protected: unsigned int m_id:16; RplASItemType m_nodeType:8; @@ -331,10 +334,10 @@ public: virtual void dump(FILE* fp, int indent); }; -class RplASFor : public RplASNode4, public RplASStatement +class RplASForIterated : public RplASNode3, public RplASStatement { public: - RplASFor(); + RplASForIterated(RplASNamedValue* variable); public: virtual void execute(); virtual void dump(FILE* fp, int indent); @@ -343,7 +346,7 @@ public: class RplASForCounted : public RplASNode5, public RplASStatement { public: - RplASForCounted(); + RplASForCounted(RplASNamedValue* variable); public: virtual void execute(); virtual void dump(FILE* fp, int indent); diff --git a/rplexpr/rpllexer.cpp b/rplexpr/rpllexer.cpp index edd7e3c..03bf088 100644 --- a/rplexpr/rpllexer.cpp +++ b/rplexpr/rpllexer.cpp @@ -429,8 +429,8 @@ void RplLexer::prepareOperators(const char* operators, // the entries of m_operators end with ' ' and id: if (m_operators.at(ix).size() == 1 + 2 && m_operators.at(ix).at(0) != m_operators.at(ix+1).at(0)){ - int id = m_operators[ix].at(2).unicode(); - m_charInfo[id] |= CC_OP_1_ONLY; + int cc = (char) m_operators[ix].at(0).unicode(); + m_charInfo[cc] |= CC_OP_1_ONLY; } } diff --git a/rplexpr/rplmfparser.cpp b/rplexpr/rplmfparser.cpp index a856d64..9138ef5 100644 --- a/rplexpr/rplmfparser.cpp +++ b/rplexpr/rplmfparser.cpp @@ -28,7 +28,9 @@ enum MFLocations{ L_PARSE_WHILE_NO_DO = 2015, L_PARSE_WHILE_NO_OD, L_PARSE_REPEAT_NO_UNTIL, - L_PARSE_REPEAT_NO_SEMI + L_PARSE_REPEAT_NO_SEMI, + L_PARSE_BODY_WRONG_ITEM, + L_PARSE_FOR_NO_TO = 2020 }; @@ -67,7 +69,7 @@ RplASItem* RplMFParser::parseIf() RplASIf* rc = new RplASIf(); rc->setPosition(m_lexer.currentPosition()); - RplASItem* condition = parseExpr(); + RplASItem* condition = parseExpr(0); if (! m_lexer.currentToken()->isKeyword(K_THEN)) syntaxError(L_PARSE_IF_NO_THEN, "'then' expected"); rc->setChild(condition); @@ -92,7 +94,7 @@ RplASItem* RplMFParser::parseWhile() RplASWhile* rc = new RplASWhile(); rc->setPosition(m_lexer.currentPosition()); - RplASItem* condition = parseExpr(); + RplASItem* condition = parseExpr(0); if (! m_lexer.currentToken()->isKeyword(K_DO)) syntaxError(L_PARSE_WHILE_NO_DO, "'do' expected"); rc->setChild2(condition); @@ -116,7 +118,7 @@ RplASItem* RplMFParser::parseRepeat() if (! m_lexer.currentToken()->isKeyword(K_UNTIL)) syntaxError(L_PARSE_REPEAT_NO_UNTIL, "'until' expected"); - RplASItem* condition = parseExpr(); + RplASItem* condition = parseExpr(0); if (! m_lexer.currentToken()->isOperator(O_SEMICOLON)) syntaxError(L_PARSE_REPEAT_NO_SEMI, "';' expected"); rc->setChild2(condition); @@ -125,10 +127,49 @@ RplASItem* RplMFParser::parseRepeat() /** * @brief Parses a for statement. + * + * Syntax: + * for [ ] [ from ] to [ step ] do + * od + * + * for in do od + * */ RplASItem* RplMFParser::parseFor() { - RplASItem*rc = NULL; + RplASNode2* rc = NULL; + const RplSourcePosition* startPosition = m_lexer.currentPosition(); + RplToken* token = m_lexer.nextNonSpaceToken(); + RplASNamedValue* var = NULL; + if (token->isTokenType(TOKEN_ID)){ + var = new RplASNamedValue(token->toString()); + var->setPosition(m_lexer.currentPosition()); + token = m_lexer.nextNonSpaceToken(); + } + if (token->isKeyword(K_IN)){ + RplASForIterated* node = new RplASForIterated(var); + rc = node; + node->setPosition(startPosition); + RplASItem* iterable = parseExpr(0); + node->setChild3(iterable); + } else { + RplASForCounted* node = new RplASForCounted(var); + rc = node; + node->setPosition(startPosition); + if (token->isKeyword(K_FROM)){ + node->setChild3(parseExpr(0)); + } + if (! token->isKeyword(K_TO)){ + syntaxError(L_PARSE_FOR_NO_TO, "'to' expected"); + } + node->setChild4(parseExpr(0)); + if (token->isKeyword(K_STEP)){ + node->setChild5(parseExpr(0)); + } + } + if (! token->isKeyword(K_DO)) + syntaxError(L_PARSE_FOR_NO_TO, "'to' expected"); + rc->setChild(parseBody(K_OD)); return rc; } @@ -180,7 +221,7 @@ RplASItem* RplMFParser::parseVarDefinition(Keyword attribute) if (! token->isOperator(O_ASSIGN, O_SEMICOLON)) syntaxError(L_DEFINITION_NO_OP, "'=' or ';' expected"); if (token->id() == O_ASSIGN){ - RplASItem* value = parseExpr(); + RplASItem* value = parseExpr(0); rc->setChild(value); token = m_lexer.currentToken(); } @@ -205,20 +246,22 @@ RplASItem* RplMFParser::parseOperand(int level) switch(token->tokenType()){ case TOKEN_OPERATOR: { - Operator op = (Operator) token->id(); - if (op == O_LPARENTH){ - rc = parseTerm(level + 1); - } else if (IS_UNARY_OP(op)){ - RplASUnaryOp* node = new RplASUnaryOp(token->id(), AST_PRE_UNARY_OP); - rc = node; - node->setChild(parseOperand(level)); - token = m_lexer.nextNonSpaceToken(); - if(token->tokenType() != TOKEN_OPERATOR || token->id() != O_RPARENT){ - QByteArray pos = startPosition->toString().toUtf8(); + Operator opId = (Operator) token->id(); + if (opId == O_LPARENTH){ + rc = parseExpr(level + 1); + token = m_lexer.currentToken(); + if(! token->isOperator(O_RPARENT)){ + char buffer[256]; // this call never comes back (exception!) syntaxError(L_PARSE_OPERAND_RPARENTH, - "')' expected. '(' is at %s", pos.constData()); + "')' expected. '(' is at %s", + startPosition->utf8(buffer, sizeof buffer)); } + } else if (IS_UNARY_OP(opId)){ + RplASUnaryOp* op = new RplASUnaryOp(token->id(), AST_PRE_UNARY_OP); + op->setPosition(m_lexer.currentPosition()); + op->setChild(parseOperand(level)); + rc = op; } break; } @@ -295,17 +338,23 @@ RplASItem* RplMFParser::parseOperand(int level) } /** - * @brief Parses a term. + * @brief Parses an expression. + * + * This method parses the part of an expression with the same parenthesis level. + * The nested parts will be processed recursivly by calling parseOperand which + * calls parseExpr in the case of inner parentheses. * - * A term is a part of an expression with the same parenthesis level. * Example: a + (3 * 7 - 2)
- * first term: 3*7-2
- * second term: a + term1
+ * expr with level 1: 3*7-2
+ * expr with level 0: a + expr1
+ * + * @precond the nextNonSpaceToken() will return the first token of the expr. + * @postcond the next token behind the expression is read * * @param depth the level of the parenthesis * @return the abstract syntax tree representing the parsed expression */ -RplASItem* RplMFParser::parseTerm(int depth){ +RplASItem* RplMFParser::parseExpr(int depth){ RplToken* token; RplASItem* top = parseOperand(depth); int lastPrio = INT_MAX; @@ -328,12 +377,8 @@ RplASItem* RplMFParser::parseTerm(int depth){ && ! m_lexer.isRightAssociative(opId))){ op->setChild(top); top = op; - } else if (prio > lastPrio){ - RplASBinaryOp* top2 = dynamic_cast(op); - op->setChild(top2->child2()); - top2->setChild2(op); } else { - // right assoc: + // right assoc or higher priority: RplASBinaryOp* top2 = dynamic_cast(top); op->setChild(top2->child2()); top2->setChild2(op); @@ -362,28 +407,18 @@ RplASItem* RplMFParser::parseTerm(int depth){ return top; } + /** - * @brief Parses an expression. + * @brief Parses an expression as a statement. * * @precond the nextNonSpaceToken() will return the first token of the expr. * @postcond all tokens belonging to the expr are read (not more!) * - * @return the tree of the expression - */ -RplASItem* RplMFParser::parseExpr() -{ - RplASItem* rc = parseTerm(0); - return rc; -} - -/** - * @brief Parses an expression as a statement. - * * @return the abstract syntax tree of the expression statement */ RplASItem* RplMFParser::parseExprStatement() { - RplASItem* item = parseTerm(0); + RplASItem* item = parseExpr(0); RplASExprStatement* statement = new RplASExprStatement(); statement->setPosition(item->position()); statement->setChild(item); @@ -487,7 +522,8 @@ RplASItem* RplMFParser::parseBody(Keyword keywordStop, Keyword keywordStop2, } lastStatement = dynamic_cast(item); if (lastStatement == NULL) - assert("wrong item type" == NULL); + error(L_PARSE_BODY_WRONG_ITEM, "wrong item type: %d", + item == NULL ? 0 : item->nodeType()); token = m_lexer.currentToken(); if ((keywordStop != K_UNDEF && token->isKeyword(keywordStop, keywordStop2)) diff --git a/rplexpr/rplmfparser.hpp b/rplexpr/rplmfparser.hpp index 2cda2a5..50f0818 100644 --- a/rplexpr/rplmfparser.hpp +++ b/rplexpr/rplmfparser.hpp @@ -15,32 +15,31 @@ class RplMFParser : public RplParser public: enum Keyword { 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_FOR, K_FROM, K_TO, K_STEP, K_IN, 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_NONE, K_TRUE, K_FALSE }; #define MF_KEYWORDS "if then else fi while do od repeat until" \ - " for from to step case of esac leave continue pass" \ + " for from to step in case of esac leave continue pass" \ " class endc endf func generator import" \ " 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, - O_MOD_ASSIGN, O_POWER_ASSIGN, O_OR_ASSIGN, O_AND_ASSIGN, - O_LSHIFT_ASSIGN, O_RSHIFT_ASSIGN, O_RSHIFT2_ASSIGN, - O_OR, O_AND, - O_EQ, O_NE, - O_LT, O_GT, O_LE, O_GE, - O_QUESTION, - O_PLUS, O_MINUS, - O_DIV, O_MOD, O_TIMES, - O_POWER, - O_XOR, O_BIT_OR, O_BIT_AND, - O_LSHIFT, O_RSHIFT, O_RSHIFT2, - O_DOT, - O_NOT, O_BIT_NOT, - O_INC, O_DEC, - O_LPARENTH, O_RPARENT, O_LBRACKET, O_RBRACKET, O_LBRACE, O_RBRACE + O_UNDEF, O_SEMI_SEMICOLON, O_SEMICOLON, O_COMMA, O_COLON, // 4 + O_ASSIGN, O_PLUS_ASSIGN, O_MINUS_ASSIGN, O_DIV_ASSIGN, O_TIMES_ASSIGN, // 8 + O_MOD_ASSIGN, O_POWER_ASSIGN, O_OR_ASSIGN, O_AND_ASSIGN, // 13 + O_LSHIFT_ASSIGN, O_RSHIFT_ASSIGN, O_RSHIFT2_ASSIGN, // 16 + O_OR, O_AND, // 18 + O_EQ, O_NE, // 20 + O_LT, O_GT, O_LE, O_GE, // 24 + O_QUESTION, // 25 + O_PLUS, O_MINUS, // 27 + O_DIV, O_MOD, O_TIMES, // 30 + O_POWER, // 31 + O_XOR, O_BIT_OR, O_BIT_AND, // 34 + O_LSHIFT, O_RSHIFT, O_RSHIFT2, // 37 + O_NOT, O_BIT_NOT, // 39 + O_INC, O_DEC, // 41 + O_DOT, O_LPARENTH, O_RPARENT, O_LBRACKET, O_RBRACKET, O_LBRACE, O_RBRACE // 48 }; #define IS_BINARY_OP(op) (Operator(op) >= O_ASSIGN && Operator(op) <= O_DOT) #define IS_UNARY_OP(op) (op==O_PLUS || op==O_MINUS || (op>=O_NOT && op<=O_DEC)) @@ -59,7 +58,6 @@ public: "**\n" \ "^ | &\n" \ "<< >> >>>\n" \ - ".\n" \ "! ~\n" \ "++ --\n" \ ". ( ) [ ] { }" @@ -73,7 +71,7 @@ public: RplASItem* parseRepeat(); RplASItem* parseFor(); RplASItem* parseVarDefinition(Keyword attribute); - RplASItem* parseExpr(); + RplASItem* parseExpr(int depth); RplASItem* parseBody(Keyword keywordStop, Keyword keywordStop2 = K_UNDEF, Operator opStop = O_UNDEF, Operator opStop2 = O_UNDEF); RplASItem* parseMethodDefinition(); @@ -85,7 +83,6 @@ public: protected: RplASArgument* parseArguments(); RplASItem* parseOperand(int level); - RplASItem* parseTerm(int depth); private: ///syntax token builder. /// Note: the super class contains a reference with the same name diff --git a/test/rplmfparser/baseTest.txt b/test/rplmfparser/baseTest.txt index 0fe593c..e989f86 100644 --- a/test/rplmfparser/baseTest.txt +++ b/test/rplmfparser/baseTest.txt @@ -1,18 +1,11 @@ -=== Globals: -= global (global) parent: +2+3*4 += (module) parent: global == Classes: - class Boolean super: - class Boolean super: - class Integer super: Float - class List super: - class Map super: - class String super: == Variables: -== Body: - = (module) parent: global - == Classes: - == Variables: - == Body: - BinOp 2 op: + (26) left: 1 right: 3 - Constant 1 value: 2 - Constant 3 value: 3 +== Body: +Expr id: 6 succ: 0 expr: 2 :1:1 + BinOp id: 2 op: + (26) left: 1 right: 4 :1:1 + const id: 1 value: 2 :0:0 + BinOp id: 4 op: * (30) left: 3 right: 5 :1:3 + const id: 3 value: 3 :1:2 + const id: 5 value: 4 :1:4 diff --git a/test/rplmfparser/defTest.txt b/test/rplmfparser/defTest.txt index 8863957..7824546 100644 --- a/test/rplmfparser/defTest.txt +++ b/test/rplmfparser/defTest.txt @@ -1,20 +1,10 @@ -=== Globals: -= global (global) parent: +Int i = 3; const lazy Str s = 'Hi'; const List l; += (module) parent: global == Classes: - class Bool super: - class Float super: - class Int super: Float - class List super: - class Map super: - class Str super: == Variables: -== Body: - = (module) parent: global - == Classes: - == Variables: - == Body: - varDef i (Int) id: 1 succ: 3 attr: 0x0 - const id: 2 value: 3 - varDef s (Str) id: 3 succ: 5 attr: 0x10 - const id: 4 value: 'Hi' - varDef l (List) id: 5 succ: 0 attr: 0x2 +== Body: +varDef i (Int) id: 1 succ: 3 attr: 0x0 :1:4 + const id: 2 value: 3 :1:8 +varDef s (Str) id: 3 succ: 5 attr: 0x10 :1:26 + const id: 4 value: 'Hi' :1:30 +varDef l (List) id: 5 succ: 0 attr: 0x2 :1:47 diff --git a/test/rplmfparser/forC1.txt b/test/rplmfparser/forC1.txt new file mode 100644 index 0000000..0ce61c6 --- /dev/null +++ b/test/rplmfparser/forC1.txt @@ -0,0 +1,19 @@ +Int a; +for b from 10 to 1 step -2 do +a += 1; +od += (module) parent: global +== Classes: +== Variables: +== Body: +varDef a (Int) id: 1 succ: 3 attr: 0x0 :1:4 +forc id: 3 var: 2 from: 4 to: 5 step: 6 body: 11 :1:7 + namedValue b id: 2 attr: 0x0 :2:4 + const id: 4 value: 10 :2:11 + const id: 5 value: 1 :2:17 + Unary 6 op: - (27) Child: 7 :2:24 + const id: 7 value: 2 :2:25 + Expr id: 11 succ: 0 expr: 9 :3:2 + BinOp id: 9 op: += (6) left: 8 right: 10 :3:2 + namedValue a id: 8 attr: 0x0 :3:2 + const id: 10 value: 1 :3:5 diff --git a/test/rplmfparser/forC2.txt b/test/rplmfparser/forC2.txt new file mode 100644 index 0000000..877a107 --- /dev/null +++ b/test/rplmfparser/forC2.txt @@ -0,0 +1,12 @@ +Int a; for to 10 do a += 1 od += (module) parent: global +== Classes: +== Variables: +== Body: +varDef a (Int) id: 1 succ: 2 attr: 0x0 :1:4 +forc id: 2 var: 0 from: 0 to: 3 step: 0 body: 7 :1:7 + const id: 3 value: 10 :1:14 + Expr id: 7 succ: 0 expr: 5 :1:22 + BinOp id: 5 op: += (6) left: 4 right: 6 :1:22 + namedValue a id: 4 attr: 0x0 :1:22 + const id: 6 value: 1 :1:25 diff --git a/test/rplmfparser/forIt1.txt b/test/rplmfparser/forIt1.txt new file mode 100644 index 0000000..a28c1ba --- /dev/null +++ b/test/rplmfparser/forIt1.txt @@ -0,0 +1,16 @@ +Map a; +for x in a do +a += 1; +od += (module) parent: global +== Classes: +== Variables: +== Body: +varDef a (Map) id: 1 succ: 3 attr: 0x0 :1:4 +forIt id: 3 var: 2 set: 4 body: 8 :1:7 + namedValue x id: 2 attr: 0x0 :2:4 + namedValue a id: 4 attr: 0x0 + Expr id: 8 succ: 0 expr: 6 :3:2 + BinOp id: 6 op: += (6) left: 5 right: 7 :3:2 + namedValue a id: 5 attr: 0x0 :3:2 + const id: 7 value: 1 :3:5 diff --git a/test/rplmfparser/ifTest1.txt b/test/rplmfparser/ifTest1.txt index 8c10fd5..ed95634 100644 --- a/test/rplmfparser/ifTest1.txt +++ b/test/rplmfparser/ifTest1.txt @@ -22,10 +22,14 @@ If id: 9 condition: 11 then: 18 else: 24 :3:11 const id: 10 value: 11 :4:3 const id: 12 value: 12 :4:8 Expr id: 18 succ: 0 expr: 14 :5:7 - BinOp id: 14 op: = (5) left: 13 right: 15 :5:7 + BinOp id: 14 op: = (5) left: 13 right: 16 :5:7 namedValue a id: 13 attr: 0x0 :5:7 - const id: 15 value: 13 :5:9 + BinOp id: 16 op: * (30) left: 15 right: 17 :5:12 + const id: 15 value: 13 :5:9 + const id: 17 value: 14 :5:14 Expr id: 24 succ: 0 expr: 20 :6:7 - BinOp id: 20 op: = (5) left: 19 right: 21 :6:7 + BinOp id: 20 op: = (5) left: 19 right: 22 :6:7 namedValue a id: 19 attr: 0x0 :6:7 - const id: 21 value: 15 :6:9 + BinOp id: 22 op: / (28) left: 21 right: 23 :6:12 + const id: 21 value: 15 :6:9 + const id: 23 value: 16 :6:14 diff --git a/test/rplmfparser/opTest1.txt b/test/rplmfparser/opTest1.txt index 01bd9b1..2315f66 100644 --- a/test/rplmfparser/opTest1.txt +++ b/test/rplmfparser/opTest1.txt @@ -1,9 +1,42 @@ -Int a; ---aa; -aa++; -a--+3*4 +Int a = 1; +Int b = 100; +--a; +b++; +a--*++b**(8-3); +a=b=(a+(b-2)*3) = (module) parent: global == Classes: == Variables: == Body: -varDef a (Int) id: 1 succ: 0 attr: 0x0 :1:4 +varDef a (Int) id: 1 succ: 3 attr: 0x0 :1:4 + const id: 2 value: 1 :1:8 +varDef b (Int) id: 3 succ: 7 attr: 0x0 :2:4 + const id: 4 value: 100 :2:8 +Expr id: 7 succ: 10 expr: 5 :2:13 + Unary 5 op: -- (41) Child: 6 :2:13 + namedValue a id: 6 attr: 0x0 :3:3 +Expr id: 10 succ: 20 expr: 9 + Unary 9 op: ++ (40) Child: 8 + namedValue b id: 8 attr: 0x0 :4:1 +Expr id: 20 succ: 32 expr: 13 :5:3 + BinOp id: 13 op: * (30) left: 12 right: 16 :5:3 + Unary 12 op: -- (41) Child: 11 + namedValue a id: 11 attr: 0x0 :5:1 + BinOp id: 16 op: ** (31) left: 14 right: 18 :5:7 + Unary 14 op: ++ (40) Child: 15 :5:4 + namedValue b id: 15 attr: 0x0 :5:7 + BinOp id: 18 op: - (27) left: 17 right: 19 :5:11 + const id: 17 value: 8 :5:10 + const id: 19 value: 3 :5:12 +Expr id: 32 succ: 0 expr: 22 :6:1 + BinOp id: 22 op: = (5) left: 21 right: 24 :6:1 + namedValue a id: 21 attr: 0x0 :6:1 + BinOp id: 24 op: = (5) left: 23 right: 26 :6:3 + namedValue b id: 23 attr: 0x0 :6:3 + BinOp id: 26 op: + (26) left: 25 right: 30 :6:6 + namedValue a id: 25 attr: 0x0 :6:6 + BinOp id: 30 op: * (30) left: 28 right: 31 :6:12 + BinOp id: 28 op: - (27) left: 27 right: 29 :6:9 + namedValue b id: 27 attr: 0x0 :6:9 + const id: 29 value: 2 :6:10 + const id: 31 value: 3 :6:13 diff --git a/test/rplmfparser/repeatTest.txt b/test/rplmfparser/repeatTest.txt new file mode 100644 index 0000000..546eb1e --- /dev/null +++ b/test/rplmfparser/repeatTest.txt @@ -0,0 +1,18 @@ +Int a; +repeat +a++; +until a != 2 * 3; += (module) parent: global +== Classes: +== Variables: +== Body: +varDef a (Int) id: 1 succ: 2 attr: 0x0 :1:4 +repeat id: 2 condition: 7 body: 5 :1:7 + Expr id: 5 succ: 0 expr: 4 + Unary 4 op: ++ (40) Child: 3 + namedValue a id: 3 attr: 0x0 :3:1 + BinOp id: 7 op: != (20) left: 6 right: 9 :4:8 + namedValue a id: 6 attr: 0x0 :4:8 + BinOp id: 9 op: * (30) left: 8 right: 10 :4:13 + const id: 8 value: 2 :4:11 + const id: 10 value: 3 :4:15 diff --git a/unittests/rplastree_test.cpp b/unittests/rplastree_test.cpp index a225c84..22585f3 100644 --- a/unittests/rplastree_test.cpp +++ b/unittests/rplastree_test.cpp @@ -24,11 +24,14 @@ public: public: void testRplASException() { try{ - RplSourcePosition pos(&m_unit, 1, 2); - throw RplASException(&pos, "simple string: %s", "Hi"); + m_reader.addSource("
", "12"); + m_source.addReader(&m_reader); + m_source.addSourceUnit(m_reader.currentSourceUnit()); + const RplSourcePosition* pos = m_source.newPosition(2); + throw RplASException(pos, "simple string: %s", "Hi"); checkF(true); } catch (RplASException exc){ - checkE("
-1 (2): simple string: Hi", exc.getMessage().constData()); + checkE("
:0:2: simple string: Hi", exc.getMessage().constData()); } } void testRplASVariant(){ diff --git a/unittests/rplmfparser_test.cpp b/unittests/rplmfparser_test.cpp index b1a8c2e..5472042 100644 --- a/unittests/rplmfparser_test.cpp +++ b/unittests/rplmfparser_test.cpp @@ -89,7 +89,7 @@ public: checkAST("repeatTest.txt", __LINE__); } void forCTest(){ - setSource("Int a;\nfor b from 1 to 10 step 2 do\na += 1;\nod"); + setSource("Int a;\nfor b from 10 to 1 step -2 do\na += 1;\nod"); RplMFParser parser(m_source, m_tree); parser.parse(); checkAST("forC1.txt", __LINE__); @@ -98,18 +98,29 @@ public: checkAST("forC2.txt", __LINE__); } void opTest(){ - setSource("--aa;\naa++;\na--+3*4"); + checkE(25, RplMFParser::O_QUESTION); + checkE(37, RplMFParser::O_RSHIFT2); + checkE(41, RplMFParser::O_DEC); + checkE(48, RplMFParser::O_RBRACE); + setSource("Int a = 1;\nInt b = 100;\n--a;\nb++;\na--*++b**(8-3);\na=b=(a+(b-2)*3)"); RplMFParser parser(m_source, m_tree); parser.parse(); checkAST("opTest1.txt", __LINE__); } + void forItTest(){ + setSource("Map a;\nfor x in a do\na += 1;\nod"); + RplMFParser parser(m_source, m_tree); + parser.parse(); + checkAST("forIt1.txt", __LINE__); + } virtual void doIt(void) { + forCTest(); + forItTest(); opTest(); ifTest(); whileTest(); repeatTest(); - forCTest(); defTest(); baseTest(); }