]> gitweb.hamatoma.de Git - reqt/commitdiff
day's work
authorhama <hama@siduction.net>
Sun, 6 Jul 2014 16:11:56 +0000 (18:11 +0200)
committerhama <hama@siduction.net>
Sun, 6 Jul 2014 16:11:56 +0000 (18:11 +0200)
16 files changed:
rplcore/rpltest.cpp
rplexpr/rplastree.cpp
rplexpr/rplastree.hpp
rplexpr/rpllexer.cpp
rplexpr/rplmfparser.cpp
rplexpr/rplmfparser.hpp
test/rplmfparser/baseTest.txt
test/rplmfparser/defTest.txt
test/rplmfparser/forC1.txt [new file with mode: 0644]
test/rplmfparser/forC2.txt [new file with mode: 0644]
test/rplmfparser/forIt1.txt [new file with mode: 0644]
test/rplmfparser/ifTest1.txt
test/rplmfparser/opTest1.txt
test/rplmfparser/repeatTest.txt [new file with mode: 0644]
unittests/rplastree_test.cpp
unittests/rplmfparser_test.cpp

index d68bfee03858b18893620ad445666681904184bb..3440f719081c2049655f979f3ff6168bbb8cbee7 100644 (file)
@@ -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<QByteArray> expLines = expectedContent.split('\n');
-        QList<QByteArray> curLines = expectedContent.split('\n');
+        QList<QByteArray> curLines = currentContent.split('\n');
         rc = assertEquals(expLines, curLines, file, lineNo);
     }
     return rc;
index 827ce7efa86d36ac60614c166852525285b3b197..b6f6c5f89cb2418c3c8ca6c4783588b835509b51 100644 (file)
@@ -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              <code>buffer</code>
+ */
+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<RplASCondition*>(m_child2);
-    if (condition == NULL)
-        throw RplASException(m_child2 == NULL ? m_position : m_child2->position(),
-                             "for statement: not a condition");
-    RplASStatement* forwarding = dynamic_cast<RplASStatement*>(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<RplASStatement*>(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"
index cf0a566bd777b677412db2b80ffa1510a31cf74c..9d9d825b984699efdb362da9c59b50d8655b4f40 100644 (file)
@@ -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);
index edd7e3c0feb8b37822399d5cd3469b4034afee2e..03bf08841a9dbeacf0affe27d42336c8383bf30b 100644 (file)
@@ -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;
         }
 
     }
index a856d642bcd6d617cfe34cbc2d4013038b9c998a..9138ef5369572c0855c246e7f4dd5bae7c53deed 100644 (file)
@@ -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 [ <var> ] [ from <start_expr> ] to <end_expr> [ step <step_expr> ] do
+ * <body> od
+ *
+ * for <var> in <iterable_expr> do <body> 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 <code>parseExpr</code> in the case of inner parentheses.
  *
- * A term is a part of an expression with the same parenthesis level.
  * Example: a + (3 * 7 - 2)<br>
- * first term: 3*7-2<br>
- * second term: a + term1<br>
+ * expr with level 1: 3*7-2<br>
+ * expr with level 0: a + expr1<br>
+ *
+ * @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<RplASBinaryOp*>(op);
-                    op->setChild(top2->child2());
-                    top2->setChild2(op);
                 } else {
-                    // right assoc:
+                    // right assoc or higher priority:
                     RplASBinaryOp* top2 = dynamic_cast<RplASBinaryOp*>(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<RplASStatement*>(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))
index 2cda2a5a12d7b27e1ec9917142ec81bc6c56310c..50f0818efa0dd5d134141bff68e5e85e4e8fed53 100644 (file)
@@ -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
index 0fe593cdf6030229a67cff444331842573426896..e989f869feed6ca43686ebbf6417f0c346f320e8 100644 (file)
@@ -1,18 +1,11 @@
-=== Globals:
-= global (global) parent: <none>
+2+3*4
+= <test> (module) parent: global
 == Classes:
-       class Boolean super: <none>
-       class Boolean super: <none>
-       class Integer super: Float
-       class List super: <none>
-       class Map super: <none>
-       class String super: <none>
 == Variables:
-== Body: <none>
-       = <test> (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 <test>:1:1
+       BinOp id: 2 op: + (26) left: 1 right: 4 <test>:1:1
+               const id: 1 value: 2 <test>:0:0
+               BinOp id: 4 op: * (30) left: 3 right: 5 <test>:1:3
+                       const id: 3 value: 3 <test>:1:2
+                       const id: 5 value: 4 <test>:1:4
index 886395768ee618cacb12043cd388aa69834444c2..78245463cdfd938b90ed47ec51c3a0f55a349da7 100644 (file)
@@ -1,20 +1,10 @@
-=== Globals:
-= global (global) parent: <none>
+Int i = 3; const lazy Str s = 'Hi'; const List l;
+= <test> (module) parent: global
 == Classes:
-       class Bool super: <none>
-       class Float super: <none>
-       class Int super: Float
-       class List super: <none>
-       class Map super: <none>
-       class Str super: <none>
 == Variables:
-== Body: <none>
-       = <test> (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 <test>:1:4
+       const id: 2 value: 3 <test>:1:8
+varDef s (Str) id: 3 succ: 5 attr: 0x10 <test>:1:26
+       const id: 4 value: 'Hi' <test>:1:30
+varDef l (List) id: 5 succ: 0 attr: 0x2 <test>:1:47
diff --git a/test/rplmfparser/forC1.txt b/test/rplmfparser/forC1.txt
new file mode 100644 (file)
index 0000000..0ce61c6
--- /dev/null
@@ -0,0 +1,19 @@
+Int a;
+for b from 10 to 1 step -2 do
+a += 1;
+od
+= <test> (module) parent: global
+== Classes:
+== Variables:
+== Body:
+varDef a (Int) id: 1 succ: 3 attr: 0x0 <test>:1:4
+forc id: 3 var: 2 from: 4 to: 5 step: 6 body: 11 <test>:1:7
+       namedValue b id: 2 attr: 0x0 <test>:2:4
+       const id: 4 value: 10 <test>:2:11
+       const id: 5 value: 1 <test>:2:17
+       Unary 6 op: - (27) Child: 7 <test>:2:24
+       const id: 7 value: 2 <test>:2:25
+       Expr id: 11 succ: 0 expr: 9 <test>:3:2
+               BinOp id: 9 op: += (6) left: 8 right: 10 <test>:3:2
+                       namedValue a id: 8 attr: 0x0 <test>:3:2
+                       const id: 10 value: 1 <test>:3:5
diff --git a/test/rplmfparser/forC2.txt b/test/rplmfparser/forC2.txt
new file mode 100644 (file)
index 0000000..877a107
--- /dev/null
@@ -0,0 +1,12 @@
+Int a; for to 10 do a += 1 od
+= <test> (module) parent: global
+== Classes:
+== Variables:
+== Body:
+varDef a (Int) id: 1 succ: 2 attr: 0x0 <test>:1:4
+forc id: 2 var: 0 from: 0 to: 3 step: 0 body: 7 <test>:1:7
+       const id: 3 value: 10 <test>:1:14
+       Expr id: 7 succ: 0 expr: 5 <test>:1:22
+               BinOp id: 5 op: += (6) left: 4 right: 6 <test>:1:22
+                       namedValue a id: 4 attr: 0x0 <test>:1:22
+                       const id: 6 value: 1 <test>:1:25
diff --git a/test/rplmfparser/forIt1.txt b/test/rplmfparser/forIt1.txt
new file mode 100644 (file)
index 0000000..a28c1ba
--- /dev/null
@@ -0,0 +1,16 @@
+Map a;
+for x in a do
+a += 1;
+od
+= <test> (module) parent: global
+== Classes:
+== Variables:
+== Body:
+varDef a (Map) id: 1 succ: 3 attr: 0x0 <test>:1:4
+forIt id: 3 var: 2 set: 4 body: 8 <test>:1:7
+       namedValue x id: 2 attr: 0x0 <test>:2:4
+       namedValue a id: 4 attr: 0x0 
+       Expr id: 8 succ: 0 expr: 6 <test>:3:2
+               BinOp id: 6 op: += (6) left: 5 right: 7 <test>:3:2
+                       namedValue a id: 5 attr: 0x0 <test>:3:2
+                       const id: 7 value: 1 <test>:3:5
index 8c10fd5c8ade4bdf3f8450bb7ae216bdc13b54c0..ed9563432245f919359661ea4e1a4f332826541a 100644 (file)
@@ -22,10 +22,14 @@ If id: 9 condition: 11 then: 18 else: 24 <test>:3:11
                const id: 10 value: 11 <test>:4:3
                const id: 12 value: 12 <test>:4:8
        Expr id: 18 succ: 0 expr: 14 <test>:5:7
-               BinOp id: 14 op: = (5) left: 13 right: 15 <test>:5:7
+               BinOp id: 14 op: = (5) left: 13 right: 16 <test>:5:7
                        namedValue a id: 13 attr: 0x0 <test>:5:7
-                       const id: 15 value: 13 <test>:5:9
+                       BinOp id: 16 op: * (30) left: 15 right: 17 <test>:5:12
+                               const id: 15 value: 13 <test>:5:9
+                               const id: 17 value: 14 <test>:5:14
        Expr id: 24 succ: 0 expr: 20 <test>:6:7
-               BinOp id: 20 op: = (5) left: 19 right: 21 <test>:6:7
+               BinOp id: 20 op: = (5) left: 19 right: 22 <test>:6:7
                        namedValue a id: 19 attr: 0x0 <test>:6:7
-                       const id: 21 value: 15 <test>:6:9
+                       BinOp id: 22 op: / (28) left: 21 right: 23 <test>:6:12
+                               const id: 21 value: 15 <test>:6:9
+                               const id: 23 value: 16 <test>:6:14
index 01bd9b122ede42e27ff0cb800fa4920f03bdd41d..2315f669589e9e3d1e3a4ddcbb4c7c5dc79a1bf0 100644 (file)
@@ -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)
 = <test> (module) parent: global
 == Classes:
 == Variables:
 == Body:
-varDef a (Int) id: 1 succ: 0 attr: 0x0 <test>:1:4
+varDef a (Int) id: 1 succ: 3 attr: 0x0 <test>:1:4
+       const id: 2 value: 1 <test>:1:8
+varDef b (Int) id: 3 succ: 7 attr: 0x0 <test>:2:4
+       const id: 4 value: 100 <test>:2:8
+Expr id: 7 succ: 10 expr: 5 <test>:2:13
+       Unary 5 op: -- (41) Child: 6 <test>:2:13
+       namedValue a id: 6 attr: 0x0 <test>:3:3
+Expr id: 10 succ: 20 expr: 9 
+       Unary 9 op: ++ (40) Child: 8 
+       namedValue b id: 8 attr: 0x0 <test>:4:1
+Expr id: 20 succ: 32 expr: 13 <test>:5:3
+       BinOp id: 13 op: * (30) left: 12 right: 16 <test>:5:3
+               Unary 12 op: -- (41) Child: 11 
+               namedValue a id: 11 attr: 0x0 <test>:5:1
+               BinOp id: 16 op: ** (31) left: 14 right: 18 <test>:5:7
+                       Unary 14 op: ++ (40) Child: 15 <test>:5:4
+                       namedValue b id: 15 attr: 0x0 <test>:5:7
+                       BinOp id: 18 op: - (27) left: 17 right: 19 <test>:5:11
+                               const id: 17 value: 8 <test>:5:10
+                               const id: 19 value: 3 <test>:5:12
+Expr id: 32 succ: 0 expr: 22 <test>:6:1
+       BinOp id: 22 op: = (5) left: 21 right: 24 <test>:6:1
+               namedValue a id: 21 attr: 0x0 <test>:6:1
+               BinOp id: 24 op: = (5) left: 23 right: 26 <test>:6:3
+                       namedValue b id: 23 attr: 0x0 <test>:6:3
+                       BinOp id: 26 op: + (26) left: 25 right: 30 <test>:6:6
+                               namedValue a id: 25 attr: 0x0 <test>:6:6
+                               BinOp id: 30 op: * (30) left: 28 right: 31 <test>:6:12
+                                       BinOp id: 28 op: - (27) left: 27 right: 29 <test>:6:9
+                                               namedValue b id: 27 attr: 0x0 <test>:6:9
+                                               const id: 29 value: 2 <test>:6:10
+                                       const id: 31 value: 3 <test>:6:13
diff --git a/test/rplmfparser/repeatTest.txt b/test/rplmfparser/repeatTest.txt
new file mode 100644 (file)
index 0000000..546eb1e
--- /dev/null
@@ -0,0 +1,18 @@
+Int a;
+repeat
+a++;
+until a != 2 * 3;
+= <test> (module) parent: global
+== Classes:
+== Variables:
+== Body:
+varDef a (Int) id: 1 succ: 2 attr: 0x0 <test>:1:4
+repeat id: 2 condition: 7 body: 5 <test>:1:7
+       Expr id: 5 succ: 0 expr: 4 
+               Unary 4 op: ++ (40) Child: 3 
+               namedValue a id: 3 attr: 0x0 <test>:3:1
+       BinOp id: 7 op: != (20) left: 6 right: 9 <test>:4:8
+               namedValue a id: 6 attr: 0x0 <test>:4:8
+               BinOp id: 9 op: * (30) left: 8 right: 10 <test>:4:13
+                       const id: 8 value: 2 <test>:4:11
+                       const id: 10 value: 3 <test>:4:15
index a225c844b4e79f1ac3385b24d63b701291cb48b6..22585f366acc6a9606e02319c7d4fa2784dc1f14 100644 (file)
@@ -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("<main>", "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("<main>-1 (2): simple string: Hi", exc.getMessage().constData());
+            checkE("<main>:0:2: simple string: Hi", exc.getMessage().constData());
         }
     }
     void testRplASVariant(){
index b1a8c2ed4b146cd736e4fffbe4f1a833695f5cce..5472042e37592d1072f22c0681871c18d4008003 100644 (file)
@@ -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();
     }