]> gitweb.hamatoma.de Git - reqt/commitdiff
day's work
authorhama <hama@siduction.net>
Sun, 29 Jun 2014 22:43:51 +0000 (00:43 +0200)
committerhama <hama@siduction.net>
Sun, 29 Jun 2014 22:43:51 +0000 (00:43 +0200)
12 files changed:
rplcore/rplcore.hpp
rplexpr/rplasclasses.cpp
rplexpr/rplasclasses.hpp
rplexpr/rplastree.cpp
rplexpr/rplastree.hpp
rplexpr/rpllexer.cpp
rplexpr/rplmfparser.cpp
rplexpr/rplmfparser.hpp
rplexpr/rplsource.cpp
rplexpr/rplsource.hpp
unittests/rplmfparser_test.cpp
unittests/rplsource_test.cpp

index 515e4428d2f6990d333cd07b3f07d79772a9fd50..168232cbad7dfadab15709fa59d6d66cb4accced 100644 (file)
@@ -31,6 +31,8 @@
 #include <QtMath>
 
 typedef unsigned char uint8_t;
+#define RPL_UNUSED(x) (void)(x)
+
 #include "rplmodules.hpp"
 #include "rplcore/rpllogger.hpp"
 #include "rplcore/rplexception.hpp"
index 4d0818019371d14f457358b14fa55dec3f665248..152eba018569d5ed6b859393a66f025fa3793fa9 100644 (file)
@@ -93,6 +93,86 @@ RplASClass*RplSymbolSpace::findClass(const QString& name) const
 {
     return NULL;
 }
+
+/**
+ * @brief Writes the content of the instance into a file.
+ *
+ * @param fp        the target file
+ * @param indent    nesting level: so many tabs will be used as prefix
+ * @param header    NULL or the headline
+ */
+void RplSymbolSpace::dump(FILE* fp, int indent, const char* header)
+{
+    char tabs[32];
+    memset(tabs, '\t', sizeof tabs);
+    tabs[(unsigned) indent < sizeof tabs ? indent : sizeof tabs - 1] = '\0';
+    if (header != NULL)
+        fprintf(fp, "%s%s\n", tabs, header);
+    fprintf(fp, "%s= %s (%s) parent: %s\n", tabs, m_name.toUtf8().constData(),
+            spaceTypeName(m_type),
+            m_parent == NULL ? "<none>" : m_parent->name().toUtf8().constData());
+    fprintf(fp, "%s== Classes:\n", tabs);
+    QList<QString> sorted;
+    sorted.reserve(m_classes.size());
+    ClassMap::iterator it;
+    for (it = m_classes.begin(); it != m_classes.end(); it++){
+       sorted.append(it.key());
+    }
+    qSort(sorted.begin(), sorted.end(), qLess<QString>());
+    QList<QString>::iterator it2;
+    for (it2 = sorted.begin(); it2 != sorted.end(); it2++){
+        RplASClass* clazz = m_classes[*it2];
+        clazz->dump(fp, indent + 1);
+    }
+
+    fprintf(fp, "== Variables:\n");
+    sorted.clear();
+    sorted.reserve(m_variables.size());
+    VariableMap::iterator it3;
+    for (it3 = m_variables.begin(); it3 != m_variables.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];
+        var->dump(fp, indent + 1);
+    }
+    fprintf(fp, "== Body:\n");
+    m_body->dump(fp, indent + 1);
+}
+
+/**
+ * @brief Returns the name of a space type.
+ *
+ * @param type  type to inspect
+ * @return      the name of the type
+ */
+const char*RplSymbolSpace::spaceTypeName(RplSymbolSpace::SymbolSpaceType type)
+{
+    const char* rc = NULL;
+    switch(type){
+    case SST_UNDEF:
+        rc = "undef";
+        break;
+    case SST_GLOBAL:
+        rc = "global";
+        break;
+    case SST_MODULE:
+        rc = "module";
+        break;
+    case SST_CLASS:
+        rc = "class";
+        break;
+    case SST_METHOD:
+        rc = "method";
+        break;
+    default:
+        rc = "?";
+        break;
+    }
+    return rc;
+}
 /**
  * @brief Returns the name of the symbol space.
  *
@@ -125,7 +205,7 @@ RplASBoolean::RplASBoolean() :
  * @param source    NULL or a source to copy
  * @return          NULL
  */
-void* RplASBoolean::newValueInstance(void* source) const
+void* RplASBoolean::newValueInstance(void*) const
 {
     return NULL;
 }
@@ -137,7 +217,7 @@ void* RplASBoolean::newValueInstance(void* source) const
  *
  * @param object    object to destroy
  */
-void RplASBoolean::destroyValueInstance(void* object) const
+void RplASBoolean::destroyValueInstance(void*) const
 {
 }
 
@@ -149,7 +229,7 @@ void RplASBoolean::destroyValueInstance(void* object) const
  * @param object    the object to test (with type QList*)
  * @return          false
  */
-bool RplASBoolean::boolValueOf(void* object) const
+bool RplASBoolean::boolValueOf(void*) const
 {
     return false;
 }
@@ -160,7 +240,7 @@ bool RplASBoolean::boolValueOf(void* object) const
  * @param object    the object to convert
  * @return          a string describing the <code>object</code>
  */
-QString RplASBoolean::toString(void* object, int maxLength) const
+QString RplASBoolean::toString(void* object, int) const
 {
     return ((RplASVariant*) object)->asBool() ? "True" : "False";
 }
@@ -192,7 +272,7 @@ RplASFloat::RplASFloat(const QString& name) :
  * @param source    NULL or a source to copy
  * @return          NULL
  */
-void* RplASFloat::newValueInstance(void* source) const
+void* RplASFloat::newValueInstance(void*) const
 {
     return NULL;
 }
@@ -204,7 +284,7 @@ void* RplASFloat::newValueInstance(void* source) const
  *
  * @param object    object to destroy
  */
-void RplASFloat::destroyValueInstance(void* object) const
+void RplASFloat::destroyValueInstance(void*) const
 {
 }
 
@@ -216,7 +296,7 @@ void RplASFloat::destroyValueInstance(void* object) const
  * @param object    the object to test
  * @return          false
  */
-bool RplASFloat::boolValueOf(void* object) const
+bool RplASFloat::boolValueOf(void*) const
 {
     return false;
 }
@@ -227,7 +307,7 @@ bool RplASFloat::boolValueOf(void* object) const
  * @param object    the object to convert
  * @return          a string describing the <code>object</code>
  */
-QString RplASFloat::toString(void* object, int maxLength) const
+QString RplASFloat::toString(void* object, int) const
 {
     QString rc;
     rc.sprintf("%f", ((RplASVariant *) object)->asFloat());
@@ -256,7 +336,7 @@ RplASInteger::RplASInteger() :
  * @param object    the object to test
  * @return          false
  */
-bool RplASInteger::boolValueOf(void* object) const
+bool RplASInteger::boolValueOf(void*) const
 {
     return false;
 }
@@ -566,3 +646,41 @@ QString RplASMap::toString(void* object, int maxLength) const
     return rc;
 }
 
+
+/** @class RplVariable rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements a variable of a symbol space.
+ */
+
+/**
+ * @brief Constructor.
+ */
+RplVariable::RplVariable(const QString& name) :
+    m_name(name),
+    m_namespace(NULL),
+    m_value(),
+    m_type(NULL)
+{
+
+}
+
+/**
+ * @brief Writes the content of the instance into a file.
+ *
+ * @param fp        the target file
+ * @param indent    nesting level: so many tabs will be used as prefix
+ * @param header    NULL or the headline
+ */
+void RplVariable::dump(FILE* fp, int indent)
+{
+    char tabs[32];
+    memset(tabs, '\t', sizeof tabs);
+    tabs[(unsigned) indent < sizeof tabs ? indent : sizeof tabs - 1] = '\0';
+
+    QByteArray name1 =  m_type == NULL ? "NoneType" : m_type->name().toUtf8();
+    QByteArray name2 =  m_name.toUtf8();
+    QByteArray val = m_value.toString().toUtf8();
+    fprintf(fp, "%s%s %s: value: %s\n", tabs,
+           name1.constData(),
+           name2.constData(), val.constData());
+}
index e4d3885ff7442c6f1a6d4604932629fbf6789656..922189058be08d12bcc7f75d9ee710adf31c66d8 100644 (file)
 class RplSymbolSpace;
 class RplVariable {
 public:
-    RplVariable();
+    RplVariable(const QString& name);
+public:
+    void dump(FILE* fp, int indent);
+
 protected:
     QString m_name;
     // NULL for "simple" variables (int, float, bool)
     RplSymbolSpace* m_namespace;
     RplASVariant m_value;
-    RplASClass* m_class;
+    RplASClass* m_type;
 };
 
 class RplSymbolSpace
@@ -43,8 +46,10 @@ public:
 public:
     RplVariable* findVariable(const QString& name) const;
     RplASClass* findClass(const QString& name) const;
+    void dump(FILE* fp, int indent, const char* header = NULL);
 public:
     static void initGlobal(RplSymbolSpace& global);
+    static const char* spaceTypeName(SymbolSpaceType type);
 private:
     SymbolSpaceType m_type;
     QString m_name;
index c17a38cefa62f261580b9b2d2bbfc2307d8f068d..865f88fef9d08c8cc8e477ba127ae0e6f9f870ff 100644 (file)
 
 unsigned int RplASItem::m_nextId = 1;
 
+#define DEFINE_TABS(indent)  \
+    char tabs[32]; \
+    memset(tabs, '\t', sizeof tabs); \
+    tabs[(unsigned) indent < sizeof tabs ? indent : sizeof tabs - 1] = '\0'
+
 /** @class RplASException rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a specific exception for the Abstract Syntax Tree.
@@ -383,6 +388,17 @@ void RplASItem::setPosition(const RplSourcePosition* position)
     m_position = position;
 }
 
+/**
+ * @brief Returns the id of the instance.
+ *
+ * @return  the id
+ */
+unsigned int RplASItem::id() const
+{
+    return m_id;
+}
+
+
 /** @class RplASExpr rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements the abstract base class of value containing items.
@@ -418,6 +434,19 @@ void RplASConstant::calc(RplASVariant& value)
     value = m_value;
 }
 
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASConstant::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sConstant %d value: %s\n", tabs, m_id,
+            m_value.toString().toUtf8().constData());
+}
+
 /**
  * @brief Returns the value of the constant.
  *
@@ -469,6 +498,17 @@ void RplASNamedValue::calc(RplASVariant& value)
 {
 
 }
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASNamedValue::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sNamedValue %d attr: 0x%x\n", tabs, m_id, m_attributes);
+}
 
 /** @class RplASNode1 rplastree.hpp "rplexpr/rplastree.hpp"
  *
@@ -617,6 +657,21 @@ int RplASUnaryOp::getOperator() const
     return m_operator;
 }
 
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASUnaryOp::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sUnary %d op: %d Child: %d\n", tabs, m_id, m_operator,
+            m_child == NULL ? 0 : m_child->id() );
+    if (m_child != NULL)
+        m_child->dump(fp, indent);
+}
+
 
 /** @class RplASStatement rplastree.hpp "rplexpr/rplastree.hpp"
  *
@@ -640,6 +695,25 @@ RplASStatement::~RplASStatement()
     delete m_successor;
     m_successor = NULL;
 }
+/**
+ * @brief Returns the next statement.
+ * @return  the next statement of a statement list
+ */
+RplASItem* RplASStatement::successor() const
+{
+    return m_successor;
+}
+
+/**
+ * @brief Sets the next statement.
+ *
+ * @param successor the successor in the statement list
+ */
+void RplASStatement::setSuccessor(RplASItem* successor)
+{
+    m_successor = successor;
+}
+
 
 
 /** @class RplASCondition rplastree.hpp "rplexpr/rplastree.hpp"
@@ -694,6 +768,21 @@ bool RplASCondition::calcAsBool()
     return rc;
 }
 
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASCondition::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sCondition %d Child: %d\n", tabs, m_id,
+            m_child == NULL ? 0 : m_child->id() );
+    if (m_child != NULL)
+        m_child->dump(fp, indent);
+}
+
 /** @class RplASFor rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a for statement.
@@ -795,6 +884,32 @@ const QString& RplASClass::name() const
     return m_name;
 }
 
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASClass::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sClass %s super: %s\n", tabs, m_name.toUtf8().constData(),
+            m_superClass == NULL
+                ? "<none>" : m_superClass->name().toUtf8().constData());
+    QList<QString> sorted;
+    sorted.reserve(m_methods.size());
+    MethodMap::iterator it;
+    for (it = m_methods.begin(); it != m_methods.end(); it++){
+       sorted.append(it.key());
+    }
+    qSort(sorted.begin(), sorted.end(), qLess<QString>());
+    QList<QString>::iterator it2;
+    for (it2 = sorted.begin(); it2 != sorted.end(); it2++){
+        RplASMethod* current = m_methods[*it2];
+        current->dump(fp, indent + 1);
+    }
+}
+
 /** @class RplASTree rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a manager for all parts of an Abstract Syntax Tree.
@@ -810,15 +925,34 @@ RplASTree::RplASTree() :
     m_global(new RplSymbolSpace(RplSymbolSpace::SST_GLOBAL, "global", NULL)),
     m_modules(),
     m_symbolSpaces(),
-    m_currentSpace(m_global)
+    m_currentSpace(NULL)
 {
-    m_symbolSpaces.append(m_global);
+    init();
 }
 
 /**
  * @brief Destructor.
  */
 RplASTree::~RplASTree()
+{
+    destroy();
+}
+
+/**
+ * @brief Initializes the instance.
+ *
+ * Used in the constructor and in clear.
+ */
+void RplASTree::init()
+{
+    m_symbolSpaces.append(m_global);
+    m_currentSpace = m_global;
+}
+
+/**
+ * @brief Frees the resources of the instance.
+ */
+void RplASTree::destroy()
 {
     SymbolSpaceMap::iterator it;
     for (it = m_symbolSpaceHeap.begin(); it != m_symbolSpaceHeap.end(); it++){
@@ -921,6 +1055,49 @@ RplSymbolSpace* RplASTree::currentSpace() const
     return m_currentSpace;
 }
 
+/**
+ * @brief Removes all content from the abstract syntax tree.
+ */
+void RplASTree::clear()
+{
+    destroy();
+    //m_global->clear();
+    m_modules.clear();
+    m_symbolSpaces.clear();
+    init();
+}
+
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param filename      filename
+ * @param flags         what to dump: sum of DMP_... flags
+ */
+void RplASTree::dump(const char* filename, int flags)
+{
+    FILE* fp = fopen(filename, "w");
+    if (fp != NULL){
+        if (flags & DMP_GLOBALS){
+            m_global->dump(fp, 0, "=== Globals:");
+        }
+        if (flags & DMP_MODULES){
+            QList<QString> sorted;
+            sorted.reserve(m_modules.size());
+            SymbolSpaceMap::iterator it;
+            for (it = m_modules.begin(); it != m_modules.end(); it++){
+               sorted.append(it.key());
+            }
+            qSort(sorted.begin(), sorted.end(), qLess<QString>());
+            QList<QString>::iterator it2;
+            for (it2 = sorted.begin(); it2 != sorted.end(); it2++){
+                RplSymbolSpace* space = m_modules[*it2];
+                space->dump(fp, 1);
+            }
+        }
+        fclose(fp);
+    }
+}
+
 /**
  * @brief Constructor.
  */
@@ -936,6 +1113,24 @@ RplASMethodCall::~RplASMethodCall()
 
 }
 
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASMethodCall::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sCall %d instance: %d args: %d\n", tabs, m_id,
+            m_child == NULL ? 0 : m_child->id(),
+            m_child2 == NULL ? 0 : m_child2->id());
+    if (m_child != NULL)
+        m_child->dump(fp, indent + 1);
+    if (m_child2 != NULL)
+        m_child->dump(fp, indent + 1);
+}
+
 void RplASMethodCall::execute()
 {
 }
@@ -961,7 +1156,7 @@ void RplASMethodCall::setMethod(RplASMethod* method)
  */
 RplASArgument* RplASMethodCall::arg1() const
 {
-    return m_arg1;
+    return dynamic_cast<RplASArgument*>(m_child2);
 }
 
 /**
@@ -971,22 +1166,103 @@ RplASArgument* RplASMethodCall::arg1() const
  */
 void RplASMethodCall::setArg1(RplASArgument* arg1)
 {
-    m_arg1 = arg1;
+    m_child2 = arg1;
 }
 
-
+/** @class RplASBinaryOp rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements binary operator for the Abstract Syntax Tree.
+ */
+/**
+ * @brief Constructor.
+ */
 RplASBinaryOp::RplASBinaryOp() :
     RplASNode2(AST_BINARY_OP),
     m_operator(0)
 {
 }
 
+/**
+ * @brief Returns the operator.
+ *
+ * @return the operator
+ */
 int RplASBinaryOp::getOperator() const
 {
     return m_operator;
 }
 
+/**
+ * @brief Sets the operator.
+ *
+ * @param op    the operator
+ */
 void RplASBinaryOp::setOperator(int op)
 {
     m_operator = op;
 }
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASBinaryOp::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sBinOp %d op: %d left: %d right: %d\n", tabs, m_id, m_operator,
+            m_child == NULL ? 0 : m_child->id(),
+            m_child2 == NULL ? 0 : m_child2->id());
+    if (m_child != NULL)
+        m_child->dump(fp, indent + 1);
+    if (m_child2 != NULL)
+        m_child->dump(fp, indent + 1);
+}
+
+/** @class RplASMethod rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements a method definition for the Abstract Syntax Tree.
+ *
+ * The special case "function" (a method without class) is included.
+ */
+/**
+ * @brief Constructor.
+ *
+ * @param name      the method name
+ * @param type      the method result type
+ */
+RplASMethod::RplASMethod(const QString& name, RplASClass* type) :
+    RplASNode2(AST_METHOD),
+    m_name(name),
+    m_type(type)
+{
+}
+
+/**
+ * @brief Writes the internals of the instance into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASMethod::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sMethod %d %s %s(", tabs, m_id,
+            m_type == NULL ? "<NoneType>" : m_type->name().toUtf8().constData(),
+            m_name.toUtf8().constData());
+    fprintf(fp, ") body: %d args: %d\n", m_child == NULL ? 0 : m_child->id(),
+            m_child2 == NULL ? 0 : m_child2->id());
+}
+
+/** @class RplASArgument rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements an argument of a method for the Abstract Syntax Tree.
+ */
+/**
+ * @brief RplASArgument::RplASArgument
+ */
+RplASArgument::RplASArgument() :
+    RplASNode2(AST_ARGUMENT),
+    RplASStatement()
+{
+}
index f31fab165f3c8458fea98b54e85642afb0b377df..5e9d91d537615d3125c5b894c648db089fe9add6 100644 (file)
@@ -15,6 +15,7 @@ enum RplASItemType {
     AST_CONSTANT,
     AST_NAMED_VALUE,
     AST_METHOD,
+    AST_ARGUMENT,
     AST_INTRINSIC_METHOD,
     AST_PRE_UNARY_OP,
     AST_POST_UNARY_OP,
@@ -113,6 +114,16 @@ public:
 public:
     const RplSourcePosition* position() const;
     void setPosition(const RplSourcePosition* position);
+    unsigned int id() const;
+public:
+    /**
+     * @brief Writes the content of the instance into a file.
+     *
+     * @param fp        the target file
+     * @param indent    nesting level: so many tabs will be used as prefix
+     * @param header    NULL or the headline
+     */
+    virtual void dump(FILE* fp, int indent) = 0;
 protected:
     unsigned int m_id:16;
     RplASItemType m_type:8;
@@ -138,6 +149,7 @@ public:
 public:
     virtual void calc(RplASVariant& value);
 public:
+    virtual void dump(FILE* fp, int indent);
     RplASVariant& value();
 private:
     RplASVariant m_value;
@@ -161,6 +173,7 @@ public:
     QString name() const;
 public:
     virtual void calc(RplASVariant& value);
+    void dump(FILE* fp, int indent);
 private:
     QString m_name;
     int m_attributes;
@@ -214,6 +227,7 @@ public:
     RplASUnaryOp(int op, RplASItemType type);
 public:
     int getOperator() const;
+    void dump(FILE* fp, int indent);
 
 private:
     int m_operator;
@@ -225,7 +239,7 @@ public:
 public:
     int getOperator() const;
     void setOperator(int op);
-
+    void dump(FILE* fp, int indent);
 private:
     int m_operator;
 };
@@ -237,6 +251,9 @@ public:
     virtual ~RplASStatement();
 public:
     virtual void execute() = 0;
+    RplASItem* successor() const;
+    void setSuccessor(RplASItem* successor);
+
 private:
     RplASItem* m_successor;
 };
@@ -248,6 +265,7 @@ public:
 public:
     void calc(RplASVariant& value);
     bool calcAsBool();
+    void dump(FILE* fp, int indent);
 };
 
 class RplASFor : public RplASNode4, public RplASStatement
@@ -270,7 +288,6 @@ class RplASArgument : public RplASNode2, public RplASStatement
 {
 public:
     RplASArgument();
-    virtual ~RplASArgument();
 };
 
 class RplASMethod;
@@ -280,18 +297,19 @@ public:
     RplASMethodCall();
     virtual ~RplASMethodCall();
 public:
+    void dump(FILE* fp, int indent);
     virtual void execute();
 
 public:
     RplASMethod* method() const;
     void setMethod(RplASMethod* method);
 
-    RplASArgument* arg1() const;
+    RplASArgument*arg1() const;
     void setArg1(RplASArgument* arg1);
-
 private:
     RplASMethod* m_method;
-    RplASArgument* m_arg1;
+    // body is child
+    // arg1 is child2
 };
 
 class RplParameter : RplASItem
@@ -309,14 +327,20 @@ class RplASClass;
 class RplASMethod : public RplASNode2
 {
 public:
-    RplASMethod();
+    RplASMethod(const QString& name, RplASClass* type);
 public:
     void execute();
+    void dump(FILE* fp, int indent);
 private:
     QString m_name;
+    RplASClass* m_type;
+    // body is m_child
+    // param1 is m_child2
 };
 
 class RplASClass {
+public:
+    typedef QMap<QString, RplASMethod*> MethodMap;
 public:
     RplASClass(const QString& name);
 public:
@@ -354,9 +378,10 @@ public:
     virtual QString toString(void *object, int maxLength = 80) const = 0;
 public:
     const QString& name() const;
+    virtual void dump(FILE* fp, int indent);
 protected:
     QString m_name;
-    QMap<QString, RplASMethod*> m_methods;
+    MethodMap m_methods;
     const RplASClass* m_superClass;
 };
 
@@ -365,6 +390,15 @@ class RplSymbolSpace;
 class RplASTree
 {
 public:
+    enum {
+        DMP_NONE,
+        DMP_GLOBALS     = 1<<1,
+        DMP_MODULES     = 1<<2,
+        DMP_SPACE_STACK = 1<<3,
+        DMP_SPACE_HEAP  = 1<<4,
+        DMP_ALL         = DMP_GLOBALS | DMP_MODULES | DMP_SPACE_STACK | DMP_SPACE_HEAP
+
+    };
     typedef QMap<QString, RplSymbolSpace*> SymbolSpaceMap;
     typedef QList<RplSymbolSpace*> SymbolSpaceStack;
 public:
@@ -379,7 +413,11 @@ public:
     SymbolSpaceStack& symbolSpaces();
     RplSymbolSpace* currentSpace() const;
     RplASClass* findClass(const QString& name);
-
+    void clear();
+    void dump(const char* filename, int flags = DMP_ALL);
+protected:
+    void init();
+    void destroy();
 private:
     // the mother of all symbol spaces.
     RplSymbolSpace* m_global;
index c74795f86f9a7bba7eaa436482f0899504f4e0af..89c3dbfdea48036b7a239dcde79f683ba072f5e5 100644 (file)
@@ -873,8 +873,9 @@ void RplLexer::undoLastToken()
  */
 RplToken*RplLexer::peekNonSpaceToken()
 {
-    nextNonSpaceToken();
+    RplToken* token = nextNonSpaceToken();
     undoLastToken();
+    return token;
 }
 /**
  * @brief Returns the maximal length of a token
@@ -943,7 +944,7 @@ RplSource* RplLexer::source()
  */
 int RplLexer::prioOfOp(int op) const
 {
-    int rc = op > 0 && op < sizeof m_prioOfOp / sizeof m_prioOfOp[0]
+    int rc = op > 0 && (unsigned) op < sizeof m_prioOfOp / sizeof m_prioOfOp[0]
             ? m_prioOfOp[op] : 0;
     return rc;
 }
index 78b5992170d1180af9713b182452c4bdfcfaa3b1..2776249c809b4fd14376faf5e31a8fe726743219 100644 (file)
@@ -201,7 +201,7 @@ RplASItem* RplMFParser::parseTerm(int depth){
     RplToken* token;
     RplSourcePosition* start = m_lexer.currentPosition();
     RplASItem* top = NULL;
-    RplASItem* item;
+    RplASItem* item = NULL;
     int lastPrio = -1;
     bool again = true;
     do {
@@ -235,7 +235,7 @@ RplASItem* RplMFParser::parseTerm(int depth){
             break;
         }
     } while(again);
-
+    return top;
 }
 
 /**
@@ -261,74 +261,85 @@ RplASItem* RplMFParser::parseBody()
 {
     RplToken* token = m_lexer.nextNonSpaceToken();
     RplASItem* item = NULL;
-    switch(token->tokenType())
-    {
-    case TOKEN_STRING:
-    case TOKEN_NUMBER:
-    case TOKEN_REAL:
-    case TOKEN_OPERATOR:
-        m_lexer.undoLastToken();
-        item = parseExpr();
-        break;
-    case TOKEN_KEYWORD:
-        switch (token->id()){
-        case K_IF:
-            item = parseIf();
-            break;
-        case K_WHILE:
-            item = parseWhile();
-            break;
-        case K_REPEAT:
-            item = parseRepeat();
-            break;
-        case K_FOR:
-            item = parseFor();
-            break;
-        case K_CLASS:
-            item = parseClass();
-            break;
-        case K_FUNCTION:
-        case K_GENERATOR:
-            item = parseMethodDefinition();
-            break;
-        case K_IMPORT:
-            parseImport();
-            break;
-        case K_CONST:
-        case K_LAZY:
-            item = parseDefinition(NULL, (Keyword) token->id());
+    RplASItem* body = NULL;
+    RplASStatement* lastStatement = NULL;
+    bool again = true;
+    while(again) {
+        switch(token->tokenType())
+        {
+        case TOKEN_STRING:
+        case TOKEN_NUMBER:
+        case TOKEN_REAL:
+        case TOKEN_OPERATOR:
+            m_lexer.undoLastToken();
+            item = parseExpr();
             break;
-        case K_INT:
-            item = parseDefinition(&RplASInteger::m_instance, K_UNDEF);
+        case TOKEN_KEYWORD:
+            switch (token->id()){
+            case K_IF:
+                item = parseIf();
+                break;
+            case K_WHILE:
+                item = parseWhile();
+                break;
+            case K_REPEAT:
+                item = parseRepeat();
+                break;
+            case K_FOR:
+                item = parseFor();
+                break;
+            case K_CLASS:
+                item = parseClass();
+                break;
+            case K_FUNCTION:
+            case K_GENERATOR:
+                item = parseMethodDefinition();
+                break;
+            case K_IMPORT:
+                parseImport();
+                break;
+            case K_CONST:
+            case K_LAZY:
+                item = parseDefinition(NULL, (Keyword) token->id());
+                break;
+            case K_INT:
+                item = parseDefinition(&RplASInteger::m_instance, K_UNDEF);
+                break;
+            case K_FLOAT:
+                parseDefinition(&RplASFloat::m_instance, K_UNDEF);
+                break;
+            case K_BOOL:
+                parseDefinition(&RplASBoolean::m_instance, K_UNDEF);
+                break;
+            default:
+                break;
+            }
             break;
-        case K_FLOAT:
-            parseDefinition(&RplASFloat::m_instance, K_UNDEF);
+        case TOKEN_ID:
+        {
+            RplASClass* clazz = m_tree.currentSpace()->findClass(token->toString());
+            if (clazz != NULL){
+                 item = parseDefinition(clazz, K_UNDEF);
+            } else {
+                m_lexer.undoLastToken();
+                item = parseExpr();
+            }
             break;
-        case K_BOOL:
-            parseDefinition(&RplASBoolean::m_instance, K_UNDEF);
+        }
+        case TOKEN_END_OF_SOURCE:
+            again = false;
             break;
         default:
             break;
         }
-        break;
-    case TOKEN_ID:
-    {
-        RplASClass* clazz = m_tree.currentSpace()->findClass(token->toString());
-        if (clazz != NULL){
-             item = parseDefinition(clazz, K_UNDEF);
+        if (body == NULL){
+            body = item;
         } else {
-            m_lexer.undoLastToken();
-            item = parseExpr();
+            lastStatement->setSuccessor(item);
         }
-        break;
+        lastStatement = dynamic_cast<RplASStatement*>(item);
     }
-    case TOKEN_END_OF_SOURCE:
-        break;
-    default:
-        break;
-    }
-    //@ToDo: add item to list
-    return NULL;
+    return body;
 }
 
 /**
@@ -370,8 +381,9 @@ void RplMFParser::parseImport()
 RplASItem* RplMFParser::parseModule(const QString& name)
 {
     m_tree.startModule(name);
-    parseBody();
+    RplASItem* body = parseBody();
     m_tree.finishModule(name);
+    return body;
 }
 /**
  * @brief Parse the input given by the source.
@@ -383,10 +395,11 @@ void RplMFParser::parse()
 
 /**
  * @brief Parses an argument list.
+ *
  * @return the first element of the argument list
  */
-RplASArgument*RplMFParser::parseArguments()
+RplASArgument* RplMFParser::parseArguments()
 {
-
+    return NULL;
 }
 
index 3e5770abd923e11090fd0edb321ed6e7394be9df..8ebe9b3e3246c4c8ed00a6d3b36d2c32acf0916f 100644 (file)
@@ -43,7 +43,7 @@ public:
         O_LPARENTH, O_RPARENT, O_LBRACKET, O_RBRACKET
     };
 #define IS_BINARY_OP(op) ((op) >= O_ASSIGN && op <= O_DOT)
-#define IS_UNARY_OP(op) (op==O_PLUS || op==O_MINUS || op>=O_NOT && op<=O_DEC)
+#define IS_UNARY_OP(op) (op==O_PLUS || op==O_MINUS || (op>=O_NOT && op<=O_DEC))
 /// \n separates the priority classes
 #define MF_OPERATORS ";; ; , :\n" \
     "= += -= /= *= %= **= |= &= <<= >>= >>>=\n" \
index 3b3b316fc2d3432ad7b80190bce9af683bc34708..850c63c32cc81c682a533721c5e8278fea0034d2 100644 (file)
@@ -315,6 +315,19 @@ RplSource::RplSource() :
  * @brief Destructor.
  */
 RplSource::~RplSource() {
+    destroy();
+}
+
+/**
+ * @brief Frees the resources of the instance.
+ */
+void RplSource::destroy()
+{
+    m_sourcePositionStack.clear();
+    m_sourcePositions.clear();
+    m_readers.clear();
+    m_sourceUnits.clear();
+    m_currentReader = NULL;
 }
 
 /**
@@ -444,6 +457,14 @@ RplReader* RplSource::currentReader() {
     return m_currentReader;
 }
 
+/**
+ * @brief Resets all states in the source.
+ */
+void RplSource::clear()
+{
+    destroy();
+}
+
 /** @class RplStringSourceUnit rplsource.hpp "rplexpr/rplsource.hpp"
  *
  * @brief Stores the state of a string based source unit.
@@ -603,6 +624,20 @@ void RplStringReader::addSource(const QString& name,
     m_currentSourceUnit = unit;
 }
 
+/**
+ * @brief Replaces the content of a source unit.
+ *
+ * @param name      name of the source unit
+ * @param content   new content
+ */
+void RplStringReader::replaceSource(const QString& name, const QString& content)
+{
+    if (m_units.contains(name)){
+        RplStringSourceUnit* unit = dynamic_cast<RplStringSourceUnit*>(m_units[name]);
+        unit->m_content = content;
+    }
+}
+
 /** @class RplFileSourceUnit rplsource.hpp "rplexpr/rplsource.hpp"
  *
  * @brief Stores the state of a file based source unit.
index 16727114b5a5dc5aec36e4938cb02485f02a8cc3..e341f44798a1bec8288e21da9c034ff57d82e65f 100644 (file)
@@ -122,6 +122,9 @@ public:
     void pushSourceUnit(RplSourceUnit* unit);
     RplSourceUnit* popSourceUnit(RplReader* reader);
     RplReader* currentReader();
+    void clear();
+protected:
+    void destroy();
 protected:
     // stack of the info about the stacked (open) source units:
     QStack<const RplSourcePosition*> m_sourcePositionStack;
@@ -163,6 +166,7 @@ public:
     virtual bool fillBuffer(int maxSize, QString& buffer, bool& hasMore);
 public:
     void addSource(const QString& name, const QString& content);
+    void replaceSource(const QString& name, const QString& content);
 };
 
 class RplFileReader;
index e5a188fe36027328f28e84e2e0263b1df22809fb..5d7d7cbecbf9427793f70cb170561de5fadc589f 100644 (file)
@@ -14,21 +14,41 @@ class TestRplMFParser : public RplTest, public RplMFParser{
 private:
     RplSource m_source;
     RplASTree m_tree;
+    RplStringReader m_reader;
 public:
     TestRplMFParser() :
         RplTest("RplMFParser"),
         RplMFParser(m_source, m_tree),
         m_source(),
-        m_tree()
-    {}
+        m_tree(),
+        m_reader(m_source)
+    {
+        m_reader.addSource("<test>", "");
+        m_source.addReader(&m_reader);
+    }
+protected:
+    void setSource(const char* content){
+        m_tree.clear();
+        m_source.clear();
+        m_reader.replaceSource("<test>", content);
+    }
 
 public:
     void baseTest(){
+        setSource("2+3*4");
+        RplMFParser parser(m_source, m_tree);
+        parser.parse();
+    }
 
+    void defTest(){
+        setSource("int i = 3; Str s = 'Hi; List l = [3, 'v4'];");
+        RplMFParser parser(m_source, m_tree);
+        parser.parse();
     }
 
     virtual void doIt(void) {
-        baseTest();
+        //baseTest();
+        //defTest();
     }
 };
 void testRplMFParser() {
index cc323e678b20d35c14eff98c0b5b9d8eda5a4db9..9d0a6cd54389c551255f6905ebd766b9fc96866c 100644 (file)
@@ -78,6 +78,14 @@ protected:
         checkE(0, unit->lineNo());
         checkOne(6, reader);
         checkOne(100, reader);
+        reader.replaceSource("source2", "content2");
+
+        unit = reader.openSourceUnit("source2");
+        QString buffer;
+        bool hasMore;
+        checkT(reader.nextLine(50, buffer, hasMore));
+        checkE("content2", buffer);
+        checkF(hasMore);
     }
 
 public: