]> gitweb.hamatoma.de Git - reqt/commitdiff
dayly work
authorhama <hama@siduction.net>
Sun, 27 Jul 2014 10:38:14 +0000 (12:38 +0200)
committerhama <hama@siduction.net>
Sun, 27 Jul 2014 10:38:14 +0000 (12:38 +0200)
rplexpr/rplasclasses.cpp
rplexpr/rplasclasses.hpp
rplexpr/rplastree.cpp
rplexpr/rplastree.hpp
rplexpr/rplmfparser.cpp
rplexpr/rplmfparser.hpp
rplexpr/rplparser.cpp
rplexpr/rplparser.hpp
test/rplmfparser/meth1.txt
test/rplmfparser/meth2.txt

index 2dc394e0f1a9ebdd26c6d02133d4ea093e12392d..0b4ce341220eddd053ff40a0ea2827a5d7377d89 100644 (file)
@@ -76,12 +76,13 @@ RplSymbolSpace::RplSymbolSpace(RplSymbolSpace::SymbolSpaceType type,
  */
 RplSymbolSpace::~RplSymbolSpace()
 {
-    QMap<QString, RplVariable*>::iterator it;
-    for (it = m_variables.begin(); it != m_variables.end(); it++){
+    ClassMap::iterator it;
+    for (it = m_classes.begin(); it != m_classes.end(); it++){
         delete it.value();
     }
-    for (it = m_variables.begin(); it != m_variables.end(); it++){
-        delete it.value();
+    MethodMap::iterator it2;
+    for (it2 = m_methods.begin(); it2 != m_methods.end(); it2++){
+        delete it2.value();
     }
 }
 
@@ -133,19 +134,34 @@ void RplSymbolSpace::dump(FILE* fp, int indent, const char* header)
         clazz->dump(fp, indent);
     }
 
-    fprintf(fp, "%s== Variables:\n", tabs);
+    fprintf(fp, "%s== Methods:\n", tabs);
     sorted.clear();
     sorted.reserve(m_variables.size());
-    VariableMap::iterator it3;
-    for (it3 = m_variables.begin(); it3 != m_variables.end(); it3++){
+    MethodMap::iterator it3;
+    for (it3 = m_methods.begin(); it3 != m_methods.end(); it3++){
        sorted.append(it3.key());
     }
     qSort(sorted.begin(), sorted.end(), qLess<QString>());
     QList<QString>::iterator it4;
     for (it4 = sorted.begin(); it4 != sorted.end(); it4++){
-        RplVariable* var = m_variables[*it4];
+        RplASMethod* var = m_methods[*it4];
+        var->dump(fp, indent);
+    }
+
+    fprintf(fp, "%s== Variables:\n", tabs);
+    sorted.clear();
+    sorted.reserve(m_variables.size());
+    VariableMap::iterator it5;
+    for (it5 = m_variables.begin(); it5 != m_variables.end(); it5++){
+       sorted.append(it5.key());
+    }
+    qSort(sorted.begin(), sorted.end(), qLess<QString>());
+    QList<QString>::iterator it6;
+    for (it6 = sorted.begin(); it6 != sorted.end(); it6++){
+        RplASVarDefinition* var = m_variables[*it6];
         var->dump(fp, indent);
     }
+
     fprintf(fp, "%s== Body:%s\n", tabs, m_body == NULL ? " <none>" : "");
     RplASNode1::dumpStatements(fp, indent, m_body);
 }
@@ -181,6 +197,17 @@ const char*RplSymbolSpace::spaceTypeName(RplSymbolSpace::SymbolSpaceType type)
     }
     return rc;
 }
+/**
+ * @brief Returns the parent of the symbol space.
+ *
+ * @return  the symbolspace of the object (module, method, class..) containing
+ *          the object belonging to the instance
+ */
+RplSymbolSpace* RplSymbolSpace::parent() const
+{
+    return m_parent;
+}
+
 /**
  * @brief Returns the body (a abstract syntax tree) of the symbol space.
  *
@@ -202,12 +229,62 @@ void RplSymbolSpace::setBody(RplASItem* body)
     m_body = body;
 }
 
+/**
+ * @brief Adds a variable to the symbol space.
+ *
+ * @param variable  the variable to add
+ * @return          NULL: success<br>
+ *                  otherwise: the already defined variable/method
+ */
+RplASItem* RplSymbolSpace::addVariable(RplASVarDefinition* variable)
+{
+    RplASItem* rc = NULL;
+    const QString& name = variable->name();
+    if (m_variables.contains(name))
+        rc = m_variables[name];
+    else if (m_methods.contains(name))
+        rc = m_methods[name];
+    else {
+        m_variables[name] = variable;
+    }
+    return rc;
+}
+
+/**
+ * @brief Adds a method to the symbol space.
+ *
+ * @param method    the method to add
+ * @return          NULL: success<br>
+ *                  otherwise: the already defined variable/method
+ */
+RplASItem* RplSymbolSpace::addMethod(RplASMethod* method)
+{
+    RplASItem* rc = NULL;
+    const QString& name = method->name();
+    if (m_variables.contains(name))
+        rc = m_variables[name];
+    else if (! m_methods.contains(name)){
+        m_methods[name] = method;
+    } else {
+        RplASMethod* oldMethod = m_methods[name];
+        do {
+            if (oldMethod->equalSignature(*method))
+                rc = oldMethod;
+            else
+                oldMethod = oldMethod->sibling();
+        } while (rc == NULL && oldMethod != NULL);
+        if (rc == NULL)
+            m_methods[name] = method;
+    }
+    return rc;
+}
+
 /**
  * @brief Returns the name of the symbol space.
  *
  * @return the name
  */
-QString RplSymbolSpace::name() const
+const QString& RplSymbolSpace::name() const
 {
     return m_name;
 }
index d1f7d9756561fba600f9d3d3fc7eb9b8d874eeb0..fdb21c5494230f7fe870c239eb874c23c71e292b 100644 (file)
@@ -37,19 +37,23 @@ public:
     };
 
 public:
-    typedef QMap<QString, RplVariable*> VariableMap;
+    typedef QMap<QString, RplASVarDefinition*> VariableMap;
     typedef QMap<QString, RplASClass*> ClassMap;
+    typedef QMap<QString, RplASMethod*> MethodMap;
 public:
     RplSymbolSpace(SymbolSpaceType type, const QString& name,
                    RplSymbolSpace* parent);
-    ~RplSymbolSpace();
+    virtual ~RplSymbolSpace();
 public:
     RplVariable* findVariable(const QString& name) const;
     RplASClass* findClass(const QString& name) const;
     void dump(FILE* fp, int indent, const char* header = NULL);
-    QString name() const;
+    const QString& name() const;
     RplASItem* body() const;
     void setBody(RplASItem* body);
+    RplASItem* addVariable(RplASVarDefinition* variable);
+    RplASItem* addMethod(RplASMethod* method);
+    RplASClass* addClass(RplASClass* clazz);
 public:
     static void initGlobal(RplSymbolSpace& global);
     static const char* spaceTypeName(SymbolSpaceType type);
@@ -58,10 +62,12 @@ private:
     QString m_name;
     VariableMap m_variables;
     ClassMap m_classes;
+    MethodMap m_methods;
     RplSymbolSpace* m_parent;
     RplASItem* m_body;
 public:
     static RplSymbolSpace m_global;
+    RplSymbolSpace* parent() const;
 };
 
 class RplASBoolean : public RplASClass {
index 2df3291124b2381cbbc7ebc8123fc673a9228ddc..70a17913c5c8a0efc240df51d866efbdbbd68177 100644 (file)
@@ -716,7 +716,7 @@ RplASNamedValue::RplASNamedValue(RplASClass* dataType,
  *
  * @return the name
  */
-QString RplASNamedValue::name() const
+const QString& RplASNamedValue::name() const
 {
     return m_name;
 }
@@ -743,6 +743,15 @@ void RplASNamedValue::dump(FILE* fp, int indent)
             m_name.toUtf8().constData(), m_id, m_attributes,
             positionStr(buffer, sizeof buffer));
 }
+/**
+ * @brief Returns the data type (class) of the instance.
+ *
+ * @return  the data type
+ */
+RplASClass* RplASNamedValue::dataType() const
+{
+    return m_dataType;
+}
 
 /** @class RplASIndexedValue rplastree.hpp "rplexpr/rplastree.hpp"
  *
@@ -815,6 +824,30 @@ void RplASVarDefinition::dump(FILE* fp, int indent)
         m_child3->dump(fp, indent + 1);
 }
 
+/**
+ * @brief Returns the name of the variable.
+ *
+ * @return  the name
+ */
+const QString& RplASVarDefinition::name() const
+{
+    RplASNamedValue* namedValue = dynamic_cast<RplASNamedValue*>(m_child2);
+    const QString& rc = namedValue == NULL ? "?" : namedValue->name();
+    return rc;
+}
+
+/**
+ * @brief Returns the data type (class) of the variable.
+ *
+ * @return  the data type
+ */
+RplASClass* RplASVarDefinition::datatype() const
+{
+    RplASNamedValue* namedValue = dynamic_cast<RplASNamedValue*>(m_child2);
+    RplASClass* rc = namedValue->dataType();
+    return rc;
+}
+
 /**
  * @brief Executes the statement.
  */
@@ -1641,6 +1674,17 @@ RplASClass::RplASClass(const QString& name) :
 {
 }
 
+/**
+ * @brief Destructor.
+ *
+ * Does nothing but forces a virtual destructor of all derived classes.
+ *
+ */
+RplASClass::~RplASClass()
+{
+
+}
+
 /**
  * @brief Return the class name.
  *
@@ -1781,9 +1825,10 @@ void RplASTree::finishModule(const QString& name)
 
 /**
  * @brief Handles the start of a new class definition.
- * @param name
+ * @param name      name of the class/method
+ * @return          the new symbol space
  */
-void RplASTree::startClassOrMethod(const QString& name,
+RplSymbolSpace* RplASTree::startClassOrMethod(const QString& name,
         RplSymbolSpace::SymbolSpaceType type)
 {
     // the stack m_modules is never empty because of "global" and modules.
@@ -1794,6 +1839,7 @@ void RplASTree::startClassOrMethod(const QString& name,
     m_symbolSpaceHeap[fullName] = space;
     m_symbolSpaces.append(space);
     m_currentSpace = space;
+    return space;
 }
 
 /**
@@ -2036,14 +2082,17 @@ void RplASBinaryOp::dump(FILE* fp, int indent)
  * @param name      the method name
  * @param type      the method result type
  */
-RplASMethod::RplASMethod(const QString& name) :
+RplASMethod::RplASMethod(const QString& name, RplASTree& tree) :
     RplASNode2(AST_METHOD),
     m_name(name),
     m_resultType(NULL),
-    m_parent(NULL)
+    m_symbols(tree.startClassOrMethod(name, RplSymbolSpace::SST_METHOD)),
+    m_sibling(NULL),
+    m_tree(tree)
 {
 }
 
+
 /**
  * @brief Writes the internals of the instance into a file.
  *
@@ -2057,34 +2106,74 @@ void RplASMethod::dump(FILE* fp, int indent)
     fprintf(fp, "%sMethod %s %s(", tabs,
             m_resultType == NULL ? "<NoneType>" : m_resultType->name().toUtf8().constData(),
             m_name.toUtf8().constData());
-    fprintf(fp, ") id: %d parent: %d args: %d body: %d %s\n", m_id,
-            m_parent == NULL ? 0 : m_parent->id(),
+    RplSymbolSpace* parent = m_symbols->parent();
+    fprintf(fp, ") id: %d parent: %s args: %d body: %d %s\n", m_id,
+            parent == NULL ? "" : parent->name().toUtf8().constData(),
             m_child2 == NULL ? 0 : m_child2->id(),
             m_child->id(),
             positionStr(buffer, sizeof buffer));
     if (m_child2 != NULL)
         m_child2->dump(fp, indent + 1);
-    m_child->dump(fp, indent + 1);
+    dumpStatements(fp, indent + 1, m_child);
+}
+RplSymbolSpace* RplASMethod::symbols() const
+{
+    return m_symbols;
 }
 /**
- * @brief Returns the parent of the method: a class or a method.
- * @return  NULL: this is a function, not a method<br>
- *          otherwise: the parent: a class or a method/func
+ * @brief Returns the name of the method
+ * @return  the name
  */
-RplASItem* RplASMethod::parent() const
+
+const QString& RplASMethod::name() const
 {
-    return m_parent;
+    return m_name;
 }
+
 /**
- * @brief Sets the parent of the method.
+ * @brief Tests whether an other method has the same signature (parameterlist).
+ * @param other     the method for comparison
+ * @return          true: same signature<br>
+ *                  false: otherwise
+ */
+bool RplASMethod::equalSignature(RplASMethod& other) const
+{
+    bool rc = true;
+    RplASExprStatement* args = dynamic_cast<RplASExprStatement*>(m_child2);
+    RplASExprStatement* otherArgs = dynamic_cast<RplASExprStatement*>(other.child2());
+
+    while(rc && (args != NULL || otherArgs != NULL)){
+        if (args == NULL || otherArgs == NULL)
+            rc = false;
+        else {
+            RplASVarDefinition* def = dynamic_cast<RplASVarDefinition*>(args->child2());
+            RplASVarDefinition* defOther = dynamic_cast<RplASVarDefinition*>(otherArgs->child2());
+            if (def->datatype() != defOther->datatype())
+                rc = false;
+        }
+    }
+    return rc;
+}
+/**
+ * @brief Returns the next overloaded method.
  *
- * @param parent    the parent: NULL or a class or a method
+ * @return  NULL: no other method available<br>
+ *          otherwise: the next method with the same name but another signature
  */
-void RplASMethod::setParent(RplASItem* parent)
+RplASMethod* RplASMethod::sibling() const
 {
-    m_parent = parent;
+    return m_sibling;
 }
 
+/**
+ * @brief Sets the next overloaded method.
+ *
+ * @param sibling   another method with the same name but another signature
+ */
+void RplASMethod::setSibling(RplASMethod* sibling)
+{
+    m_sibling = sibling;
+}
 
 /** @class RplASArgument rplastree.hpp "rplexpr/rplastree.hpp"
  *
index fbb8cc5f5b8baa260b2f32ec341e0df59ebce09e..26487d0a23a85950758011cb91f3ff8697aace47 100644 (file)
@@ -299,10 +299,12 @@ public:
     RplASNamedValue(RplASClass* dataType,
                     const QString& name, int attributes);
 public:
-    QString name() const;
+    const QString& name() const;
 public:
     virtual void calc(RplASVariant& value);
     void dump(FILE* fp, int indent);
+    RplASClass* dataType() const;
+
 protected:
     QString m_name;
     int m_attributes;
@@ -333,6 +335,8 @@ public:
     virtual void execute();
     virtual void calc(RplASVariant& value);
     void dump(FILE* fp, int indent);
+    const QString& name() const;
+    RplASClass* datatype() const;
 };
 
 class RplASExprStatement : public RplASNode2, public RplASStatement
@@ -474,20 +478,28 @@ private:
 
 
 class RplASClass;
+class RplSymbolSpace;
 class RplASMethod : public RplASNode2
 {
 public:
-    RplASMethod(const QString& name);
+    RplASMethod(const QString& name, RplASTree& tree);
 public:
     void execute();
     void dump(FILE* fp, int indent);
-    RplASItem* parent() const;
-    void setParent(RplASItem* parent);
+    RplSymbolSpace* symbols() const;
+
+    const QString& name() const;
+    bool equalSignature(RplASMethod& other) const;
+    RplASMethod* sibling() const;
+    void setSibling(RplASMethod* sibling);
 
 private:
     QString m_name;
     RplASClass* m_resultType;
-    RplASItem* m_parent;
+    RplSymbolSpace* m_symbols;
+    // chain over all overloaded methods (same name, other signature):
+    RplASMethod* m_sibling;
+    RplASTree& m_tree;
 };
 
 class RplASClass {
@@ -495,6 +507,7 @@ public:
     typedef QMap<QString, RplASMethod*> MethodMap;
 public:
     RplASClass(const QString& name);
+    virtual ~RplASClass();
 public:
     /**
      * @brief Creates a value object (used in RplASVariant).
@@ -559,7 +572,7 @@ public:
 public:
     bool startModule(const QString& name);
     void finishModule(const QString& name);
-    void startClassOrMethod(const QString& name,
+    RplSymbolSpace* startClassOrMethod(const QString& name,
         RplSymbolSpace::SymbolSpaceType type);
     void finishClassOrMethod(const QString& name);
     SymbolSpaceStack& symbolSpaces();
index e15e695e5ceba15a1851b0deae0fcd919d130881..08a2624836dd9812ce77406d6ade556342af0a24 100644 (file)
@@ -55,7 +55,9 @@ enum MFLocations{
     L_PARSE_PARAMLIST_NO_PARENTH,
     L_PARSE_PARAMLIST_NO_PARENTH2,
     L_PARSE_METH_NO_END     = 2045,
-    L_PARSE_METH_NO_END2
+    L_PARSE_METH_NO_END2,
+    L_PARSE_VAR_DEF_ALREADY_DEFINED,
+    L_PARSE_VAR_DEF_ALREADY_DEFINED2
 };
 
 /** @class RplMFParser rpllexer.hpp "rplexpr/rplmfparser.hpp"
@@ -153,8 +155,8 @@ RplASItem* RplMFParser::parseRepeat()
  *
  * for <var> in <iterable_expr> do <body> od
  *
- * @post    the token behind the do is read
- * @return  the abstract syntax tree of the for statement
+ * @post            the token behind the do is read
+ * @return          the abstract syntax tree of the for statement
  */
 RplASItem* RplMFParser::parseFor()
 {
@@ -249,6 +251,11 @@ RplASItem* RplMFParser::parseVarDefinition(RplASNamedValue::Attributes attribute
         rc->setChild3(value);
         token = m_lexer.currentToken();
     }
+    RplSymbolSpace* symbols = m_tree.currentSpace();
+    RplASItem* oldSymbol = symbols->addVariable(rc);
+    if (oldSymbol != NULL)
+        error(L_PARSE_VAR_DEF_ALREADY_DEFINED, oldSymbol->position(),
+              "symbol already defined", "previous definition");
     return rc;
 }
 
@@ -532,7 +539,7 @@ RplASItem* RplMFParser::parseOperand(int level, RplASItem* parent)
         } else if (opId == O_LPARENTH){
             rc = parseExpr(level + 1);
             token = m_lexer.currentToken();
-            if(! token->isOperator(O_RPARENT)){
+            if(! token->isOperator(O_RPARENTH)){
                 // this call never comes back (exception!)
                 syntaxError(L_PARSE_OPERAND_RPARENTH,
                             "')' expected", "(", startPosition);
@@ -588,7 +595,7 @@ RplASItem* RplMFParser::parseOperand(int level, RplASItem* parent)
 
                 rc = call;
                 token = m_lexer.nextNonSpaceToken();
-                if (! token->isOperator(O_RPARENT)){
+                if (! token->isOperator(O_RPARENTH)){
                     m_lexer.undoLastToken();
                     RplASArgument* args = parseArguments();
                     call->setChild2(args);
@@ -792,11 +799,11 @@ RplASItem* RplMFParser::parseBody(Keyword keywordStop, Keyword keywordStop2,
                     item = parseFor();
                     break;
                 case K_CLASS:
-                    item = parseClass();
+                    parseClass();
                     break;
                 case K_FUNCTION:
                 case K_GENERATOR:
-                    item = parseMethodDefinition(NULL);
+                    parseMethod();
                     break;
                 case K_IMPORT:
                     parseImport();
@@ -827,7 +834,7 @@ RplASItem* RplMFParser::parseBody(Keyword keywordStop, Keyword keywordStop2,
             default:
                 break;
             }
-            if (again){
+            if (again && item != NULL){
                 if (body == NULL){
                     body = item;
                 } else {
@@ -898,7 +905,7 @@ RplASExprStatement* RplMFParser::parseParameterList(){
         }
         last = current;
     } while(m_lexer.currentToken()->isOperator(O_COMMA));
-    if (! m_lexer.currentToken()->isOperator(O_RPARENT))
+    if (! m_lexer.currentToken()->isOperator(O_RPARENTH))
         syntaxError(L_PARSE_PARAMLIST_NO_PARENTH, ") expected", ")", startPos);
     m_lexer.nextNonSpaceToken();
     return rc;
@@ -907,13 +914,15 @@ RplASExprStatement* RplMFParser::parseParameterList(){
 /**
  * @brief Parses a class definition.
  *
- * @pre     token "func" is read
- * @post    token behind "endf" is read
- * @return  the node in an abstract syntax tree
+ * The method definition will be stored in the symbol space of the parent
+ *
+ * @pre             token "func" is read
+ * @post            token behind "endf" is read
+ * @return          NULL
  */
-RplASMethod*RplMFParser::parseMethodDefinition(RplASItem* parent)
+void RplMFParser::parseMethod()
 {
-    RplASMethod* rc = NULL;
+    RplASMethod* method = NULL;
     const RplSourcePosition* startPos = m_lexer.currentPosition();
     RplToken* token = m_lexer.nextNonSpaceToken();
     if (! token->isTokenType(TOKEN_ID))
@@ -932,37 +941,43 @@ RplASMethod*RplMFParser::parseMethodDefinition(RplASItem* parent)
     token = m_lexer.nextNonSpaceToken();
     if (! token->isOperator(O_LPARENTH, O_COLON))
         syntaxError(L_PARSE_METH_NO_LPARENTH, "'(' or ':' expected");
-    RplASExprStatement* parameterList;
+
+    RplASExprStatement* parameterList = NULL;
+    method = new RplASMethod(name, m_tree);
+    method->setPosition(startPos);
+    RplSymbolSpace* symbols = m_tree.currentSpace();
+    symbols->addMethod(method);
+
     if (token->isOperator(O_LPARENTH)){
       token = m_lexer.nextNonSpaceToken();
-      if (token->isOperator(O_RPARENT)){
+      if (token->isOperator(O_RPARENTH)){
           token = m_lexer.nextNonSpaceToken();
       } else {
           parameterList = parseParameterList();
+          method->setChild2(parameterList);
       }
     }
     if (! token->isOperator(O_COLON))
         syntaxError(L_PARSE_METH_NO_COLON, "':' expected");
-    rc = new RplASMethod(name);
-    rc->setParent(parent);
-    rc->setPosition(startPos);
-    rc->setChild2(parameterList);
-    rc->setChild(parseBody(K_ENDF));
+
+    method->setChild(parseBody(K_ENDF));
     if (! m_lexer.currentToken()->isKeyword(K_ENDF))
         syntaxError(L_PARSE_METH_NO_END, "end of function not found", "endf",
                     startPos);
     m_lexer.nextNonSpaceToken();
-    return rc;
+    m_tree.finishClassOrMethod(name);
 }
 
 /**
  * @brief Parses a class definition.
  * @return  the node in an abstract syntax tree
  */
-RplASItem*RplMFParser::parseClass()
+void RplMFParser::parseClass()
 {
-    RplASItem* rc = NULL;
-    return rc;
+    //RplASItem* clazz = NULL;
+    QString name = "";
+
+    m_tree.finishClassOrMethod(name);
 }
 
 /**
@@ -1021,7 +1036,7 @@ RplASArgument* RplMFParser::parseArguments()
     bool again = false;
     do {
         RplASItem* expr = parseExpr(0);
-        if (! m_lexer.currentToken()->isOperator(O_COMMA, O_RPARENT))
+        if (! m_lexer.currentToken()->isOperator(O_COMMA, O_RPARENTH))
             syntaxError(L_PARSE_ARGS_NO_COMMA_OR_PARENT, "',' or ')' expected");
         again = m_lexer.currentToken()->isOperator(O_COMMA);
         RplASArgument* current = new RplASArgument();
index dcee6ec6847efb71fda9d0bd4aa13159200f7b94..0530f47ecf25e27c578b42cc68fd65f6a3175a95 100644 (file)
@@ -42,7 +42,7 @@ public:
         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
+        O_DOT, O_LPARENTH, O_RPARENTH, 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))
@@ -75,8 +75,8 @@ public:
     RplASItem* parseExpr(int depth);
     RplASItem* parseBody(Keyword keywordStop, Keyword keywordStop2 = K_UNDEF,
                          Operator opStop = O_UNDEF, Operator opStop2 = O_UNDEF);
-    RplASMethod*parseMethodDefinition(RplASItem* parent);
-    RplASItem* parseClass();
+    void parseMethod();
+    void parseClass();
     void parseImport();
     RplASItem* parseModule(const QString& name);
     void parse();
index bc9bcd68119375d3f86c03acd1ef09841c9e01fc..4ed24f8b82562d160fa06b8e78547040836a9cf9 100644 (file)
@@ -188,6 +188,25 @@ void RplParser::error(int location, const char* format, ...)
     if (++m_errors >= m_maxErrors)
         throw RplParserStop("too many errors");
 }
+/**
+ * @brief Adds an error message with an additional info message.
+ *
+ * If too much errors an exception will be thrown to stop parsing.
+ *
+ * @param location  unique id of the error/warning message
+ * @param position  source position of the additional message
+ * @param message   describes the error
+ * @param message2  the additional message
+ * @param ...       optional: the variable argument list
+ */
+void RplParser::error(int location, const RplSourcePosition* position,
+                      const char* message, const char* message2)
+{
+    addSimpleMessage(LT_ERROR, location, m_lexer.currentPosition(), message);
+    addSimpleMessage(LT_INFO, location + 1, position, message2);
+    if (++m_errors >= m_maxErrors)
+        throw RplParserStop("too many errors");
+}
 
 /**
  * @brief Adds a warning message.
index 5b40149a6f8959153a0bb4d6266888c9d6451e1d..8e22aa5e6cba3eb480e954c24283569b98f43192 100644 (file)
@@ -48,6 +48,8 @@ public:
     void syntaxError(int location, const char* message, const char* symbol,
                      const RplSourcePosition* position);
     void error(int location, const char* format, ...);
+    void error(int location, const RplSourcePosition* position,
+               const char* message, const char* message2);
     void warning(int location, const char* format, ...);
 
 protected:
index 70435a3bc2376ae3d96edff564972a1dd5bb4b74..f0ef7ac0dd8c84b3f6a32d603bd02681ddf2743d 100644 (file)
@@ -3,5 +3,14 @@ func Float pi: 3.1415; endf func Str delim(): '/' endf;
 == Classes:
 == Variables:
 == Body:
-Method 1 <NoneType> pi() body: 4 args: 36816 <test>:0:0
-Method 4 <NoneType> delim() body: 0 args: 36816 <test>:1:28
+Method <NoneType> pi() id: 1 parent: 0 args: 0 body: 4 <test>:0:0
+       Method <NoneType> delim() id: 4 parent: 0 args: 0 body: 6 <test>:1:28
+               Expr id: 6 expr: 5 succ: 0 <test>:1:46
+                       const id: 5 value: '/' <test>:1:46
+       Expr id: 6 expr: 5 succ: 0 <test>:1:46
+               const id: 5 value: '/' <test>:1:46
+Method <NoneType> delim() id: 4 parent: 0 args: 0 body: 6 <test>:1:28
+       Expr id: 6 expr: 5 succ: 0 <test>:1:46
+               const id: 5 value: '/' <test>:1:46
+Expr id: 6 expr: 5 succ: 0 <test>:1:46
+       const id: 5 value: '/' <test>:1:46
index ef6527576a0f56592fdd3f284ad8682775a373d2..df66892b31584bf34854d2d248e68e6c87b029ef 100644 (file)
@@ -5,4 +5,51 @@ rc endf
 == Classes:
 == Variables:
 == Body:
-Method 4 <NoneType> fac() body: 0 args: 3 <test>:0:55
+Method <NoneType> fac() id: 4 parent: 0 args: 3 body: 6 <test>:0:55
+       Expr id: 3 expr: 2 succ: 0 
+               varDef n id: 2 namedValue: 1 value: 0 succ: 0 <test>:1:23
+                       namedValue n id: 1 attr: 0x22 <test>:1:23
+       varDef rc id: 6 namedValue: 5 value: 0 succ: 7 <test>:2:4
+               namedValue rc id: 5 attr: 0x0 <test>:2:4
+       If id: 7 condition: 9 then: 14 else: 24 succ: 26<test>:2:8
+               BinOp id: 9 op: <= (23) left: 8 right: 10 <test>:2:14
+                       namedValue rc id: 8 attr: 0x0 <test>:2:14
+                       const id: 10 value: 1 <test>:2:17
+               Expr id: 14 expr: 12 succ: 0 <test>:2:27
+                       BinOp id: 12 op: = (5) left: 11 right: 13 <test>:2:27
+                               namedValue rc id: 11 attr: 0x0 <test>:2:27
+                               const id: 13 value: 1 <test>:2:29
+               Expr id: 24 expr: 16 succ: 0 <test>:2:39
+                       BinOp id: 16 op: = (5) left: 15 right: 18 <test>:2:39
+                               namedValue rc id: 15 attr: 0x0 <test>:2:39
+                               BinOp id: 18 op: * (30) left: 17 right: 19 <test>:2:42
+                                       namedValue n id: 17 attr: 0x0 <test>:2:42
+                                       call fac Id: 19 args: 23 parent: 0 succ: 0 <test>:2:46
+                                               arg 1 id: 23 expr: 21 succ: 0
+                                                       BinOp id: 21 op: - (27) left: 20 right: 22 <test>:2:48
+                                                               namedValue n id: 20 attr: 0x0 <test>:2:48
+                                                               const id: 22 value: 1 <test>:2:49
+       Expr id: 26 expr: 25 succ: 0 <test>:3:3
+               namedValue rc id: 25 attr: 0x0 <test>:3:3
+varDef rc id: 6 namedValue: 5 value: 0 succ: 7 <test>:2:4
+       namedValue rc id: 5 attr: 0x0 <test>:2:4
+If id: 7 condition: 9 then: 14 else: 24 succ: 26<test>:2:8
+       BinOp id: 9 op: <= (23) left: 8 right: 10 <test>:2:14
+               namedValue rc id: 8 attr: 0x0 <test>:2:14
+               const id: 10 value: 1 <test>:2:17
+       Expr id: 14 expr: 12 succ: 0 <test>:2:27
+               BinOp id: 12 op: = (5) left: 11 right: 13 <test>:2:27
+                       namedValue rc id: 11 attr: 0x0 <test>:2:27
+                       const id: 13 value: 1 <test>:2:29
+       Expr id: 24 expr: 16 succ: 0 <test>:2:39
+               BinOp id: 16 op: = (5) left: 15 right: 18 <test>:2:39
+                       namedValue rc id: 15 attr: 0x0 <test>:2:39
+                       BinOp id: 18 op: * (30) left: 17 right: 19 <test>:2:42
+                               namedValue n id: 17 attr: 0x0 <test>:2:42
+                               call fac Id: 19 args: 23 parent: 0 succ: 0 <test>:2:46
+                                       arg 1 id: 23 expr: 21 succ: 0
+                                               BinOp id: 21 op: - (27) left: 20 right: 22 <test>:2:48
+                                                       namedValue n id: 20 attr: 0x0 <test>:2:48
+                                                       const id: 22 value: 1 <test>:2:49
+Expr id: 26 expr: 25 succ: 0 <test>:3:3
+       namedValue rc id: 25 attr: 0x0 <test>:3:3