From f11daa651f974d293972b3e85007db0b6a1e629c Mon Sep 17 00:00:00 2001 From: hama Date: Sat, 21 Jun 2014 01:50:49 +0200 Subject: [PATCH] implementation of Abstract Syntax Tree --- rplexpr/rplasclasses.cpp | 183 +++++++++++++++++++++++++++++++++++++++ rplexpr/rplasclasses.hpp | 49 +++++++++++ rplexpr/rplastree.cpp | 121 ++++++++++++++++++++++++++ rplexpr/rplastree.hpp | 72 +++++++++++++-- rplexpr/rplexpr.hpp | 1 + rplstatic/rplstatic.pro | 6 +- unittests/unittests.pro | 3 +- 7 files changed, 425 insertions(+), 10 deletions(-) create mode 100644 rplexpr/rplasclasses.cpp create mode 100644 rplexpr/rplasclasses.hpp diff --git a/rplexpr/rplasclasses.cpp b/rplexpr/rplasclasses.cpp new file mode 100644 index 0000000..f37101d --- /dev/null +++ b/rplexpr/rplasclasses.cpp @@ -0,0 +1,183 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#include "rplcore/rplcore.hpp" +#include "rplexpr/rplexpr.hpp" + +/** @class RplASList rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements the class of a list. + * + * A list is a container of any values. Values can be selected by the index. + */ +/** + * @brief Constructor. + */ +RplASList::RplASList() : + RplASClass("List") +{ +} + +/** + * @brief Creates a value object (used in RplASVariant). + * + * @param source NULL or a source to copy + * @return a new value object (specific for the class) + */ +void* RplASList::newValueInstance(void* source) +{ + QList* rc = new QList(); + if (source != NULL){ + QList* source2 = (QList*) source; + rc->reserve(source2->size()); + QList::iterator it; + for (it = source->begin(); + it != source->end(); + it++){ + // deleting in destroyValue(): + rc->append(new RplASValue(*it)); + } + } + return (void*) rc; +} + +/** + * @brief Destroyes the given object. + * + * The object must be created by newValueInstance(). + * + * @param object object to destroy + */ +void RplASList::destroyValueInstance(void* object) +{ + delete (QList*) object; +} + +/** @class RplASMap rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements the class of a map. + * + * A map is a container of (key, value) pairs. + * Values can be selected by the key. + */ +/** + * @brief Constructor. + */ +RplASMap::RplASMap() : + RplASClass("Map") +{ +} +/** + * @brief Creates a value object (used in RplASVariant). + * + * @param source NULL or a source to copy + * @return a new value object (specific for the class) + */ +void* RplASMap::newValueInstance(void* source) +{ + QMap* rc = new QMap(); + if (source != NULL){ + QMap* source2 = + (QMap*) source; + rc->reserve(source2->size()); + QMap::iterator it; + for (it = source->begin(); + it != source->end(); + it++){ + // deleting in destroyValue(): + rc->append(new RplASValue(*it)); + } + } + return (void*) rc; +} + +/** + * @brief Destroyes the given object. + * + * The object must be created by newValueInstance(). + * + * @param object object to destroy + */ +void RplASMap::destroyValueInstance(void* object) +{ + delete (QMap*) object; +} + +/** @class RplASString rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements the class of a string. + * + * A string is a mutable character sequence. + */ +/** + * @brief Constructor. + */ +RplASString::RplASString() : + RplASClass("String") +{ +} +/** + * @brief Creates a value object (used in RplASVariant). + * + * @param source NULL or a source to copy + * @return a new value object (specific for the class) + */ +void* RplASString::newValueInstance(void* source) +{ + QString* rc = source == NULL ? new QString() : new QString(*(QString*) source); + return (void*) rc; +} + +/** + * @brief Destroyes the given object. + * + * The object must be created by newValueInstance(). + * + * @param object object to destroy + */ +void RplASString::destroyValueInstance(void* object) +{ + delete (QString*) object; +} + +/** @class RplASNumber rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements the class of a Number. + * + * A Number is a real value. + */ +/** + * @brief Constructor. + */ +RplASNumber::RplASNumber() : + RplASClass("Number") +{ +} +/** + * @brief Creates a value object (used in RplASVariant). + * + * @param source NULL or a source to copy + * @return NULL + */ +void* RplASNumber::newValueInstance(void* source) +{ + return null; +} + +/** + * @brief Destroyes the given object. + * + * The object must be created by newValueInstance(). + * + * @param object object to destroy + */ +void RplASNumber::destroyValueInstance(void* object) +{ +} + diff --git a/rplexpr/rplasclasses.hpp b/rplexpr/rplasclasses.hpp new file mode 100644 index 0000000..c456b5e --- /dev/null +++ b/rplexpr/rplasclasses.hpp @@ -0,0 +1,49 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#ifndef RPLASCLASSES_HPP +#define RPLASCLASSES_HPP + +class RplASList : public RplASClass { +public: + RplASList(); + ~RplASList(); +public: + void* newValueInstance(void* source = NULL); + void destroyValueInstance(void* object); +}; + +class RplASMap : public RplASClass { +public: + RplASMap(); + ~RplASMap(); +public: + void* newValueInstance(void* source = NULL); + void destroyValueInstance(void* object); +}; + +class RplASNumber : public RplASClass { +public: + RplASNumber(); + ~RplASNumber(); +public: + void* newValueInstance(void* source = NULL); + void destroyValueInstance(void* object); +}; + +class RplASString : public RplASClass { +public: + RplASString(); + ~RplASString(); +public: + void* newValueInstance(void* source = NULL); + void destroyValueInstance(void* object); +}; + +#endif // RPLASCLASSES_HPP diff --git a/rplexpr/rplastree.cpp b/rplexpr/rplastree.cpp index 411614a..9edb194 100644 --- a/rplexpr/rplastree.cpp +++ b/rplexpr/rplastree.cpp @@ -9,6 +9,109 @@ #include "rplcore/rplcore.hpp" #include "rplexpr/rplexpr.hpp" +/** @class RplASVariant rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements a class which can be one of the basic types. + * + */ +RplASVariant::RplASVariant() : + m_dataType(DT_UNDEF), + // m_value(), + m_class(NULL) +{ +} +/** + * @brief Destructor. + */ +RplASVariant::~RplASVariant() +{ + destroyValue(); + m_dataType = DT_UNDEF; +} + +/** + * @brief Copy constructor. + * @param source the source to copy + */ +RplASVariant::RplASVariant(const RplASVariant& source): + m_dataType(source.m_dataType), + // m_value + m_class(source.m_class) +{ +} + +/** + * @brief Copies the value. + * @param source the source to copy + */ +void RplASVariant::copyValue(const RplASVariant& source) +{ + switch(source.m_dataType) + { + case DT_NUMBER: + m_value.m_number = source.m_value.m_number; + break; + case DT_STRING: + // deleting in destroyValue(): + m_value.m_string = new QString(source.m_value.m_string); + break; + case DT_LIST: + { + break; + } + case DT_MAP: + { + m_value.m_map = new QList(); + m_value.m_map.reserve(source.m_value.m_list.size()); + QList::iterator it; + for (it = source.m_value.m_list.begin(); + it != source.m_value.m_list.end(); + it++){ + // deleting in destroyValue(): + m_value.m_list.append(new RplASValue(*it)); + } + break + } + case DT_OBJECT: + // deleting in destroyValue(): + m_value.m_object = m_class->newValueInstance(source.m_value.m_object); + break; + default: + break; + } +} + +/** + * @brief Frees the resources of the instance. + */ +void RplASVariant::destroyValue() +{ + switch(source.m_dataType) + { + case DT_NUMBER: + break; + case DT_STRING: + // deleting in destroyValue(): + m_value.m_string = delete m_value.m_string; + m_value.m_string = NULL; + break; + case DT_LIST: + delete m_value.m_list; + m_value.m_list = NULL; + break; + case DT_MAP: + delete m_value.m_map; + m_value.m_map = NULL; + break; + case DT_OBJECT: + m_map.destroyValueInstance(m_value.m_object); + m_value.m_object = NULL; + break; + default: + break; + } +} + /** @class RplASItem rplastree.hpp "rplexpr/rplastree.hpp" * * @brief Implements the abstract base class of all entries of an AST. @@ -306,3 +409,21 @@ RplASWhile::RplASWhile() : */ RplASWhile::~RplASWhile() { +} +/** @class RplASClass rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements the base class of a Abstract Syntax Tree class. + * + * This class is abstract. + */ +/** + * @brief Constructor. + */ +RplASClass::RplASClass(const QString& name) : + m_name(name), + m_methods(), + m_superClass(NULL) +{ +} + + diff --git a/rplexpr/rplastree.hpp b/rplexpr/rplastree.hpp index f1bfb72..690136c 100644 --- a/rplexpr/rplastree.hpp +++ b/rplexpr/rplastree.hpp @@ -59,6 +59,37 @@ enum RplASUnaryOperator { ASUOP_POST_INCREMENT, ASUOP_PRE_INCREMENT }; +class RplASClass; +class RplASVariant { +public: + enum DataType { + DT_UNDEF, + DT_NUMBER, + DT_STRING, + DT_MAP, + DT_LIST, + DT_OBJECT + }; + +public: + RplASVariant(); + ~RplASVariant(); + RplASVariant(const RplASVariant& source); + RplASVariant& operator=(const RplASVariant& source); +protected: + void copyValue(const RplASVariant& source); + void destroyValue(); +private: + DataType m_dataType; + union { + qreal m_number; + QString* m_string; + QMap m_map; + QList m_list; + void* m_object; + } m_value; + RplASClass* m_class; +}; class RplASTree; class RplASItem @@ -77,7 +108,7 @@ class RplASExpr public: RplASExpr(); public: - virtual QVariant calc() = null; + virtual QVariant calc() = 0; }; class RplASValue : public RplASItem, public RplASExpr @@ -183,7 +214,7 @@ public: virtual ~RplArgument(); }; -class RplAsCall : public RplASItem, public RplASStatement +class RplAsMethodCall : public RplASNode2, public RplASStatement { public: RplArgument(); @@ -203,17 +234,44 @@ private: RplASValue* m_default; }; -class RplASFunction : public RplASNodeMany + +class RplASClass; +class RplASMethod : public RplASNode2, public RplASStatement { public: - RplASFunction(const QString& name); - virtual ~RplASFunction(); + RplASMethod(); +public: + void execute(); +private: + QString m_name; +}; + +class RplASClass { +public: + RplASClass(const QString& name); +public: + /** + * @brief Creates a value object (used in RplASVariant). + * + * @param source NULL or a source to copy + * @return a new value object (specific for the class) + */ + void* newValueInstance(void* source = NULL) = 0; + /** + * @brief Destroyes the given object. + * + * The object must be created by newValueInstance(). + * + * @param object object to destroy + */ + void destroyValueInstance(void* object) = 0; protected: - RplASItemType* body; - RplArgument* arg; QString m_name; + QMap m_methods; + RplASClass* m_superClass; }; + class RplASTree { public: diff --git a/rplexpr/rplexpr.hpp b/rplexpr/rplexpr.hpp index 62437c1..64b2ceb 100644 --- a/rplexpr/rplexpr.hpp +++ b/rplexpr/rplexpr.hpp @@ -21,5 +21,6 @@ #include "rplexpr/rplsource.hpp" #include "rplexpr/rpllexer.hpp" #include "rplexpr/rplastree.hpp" +#include "rplexpr/rplasclasses.hpp" #endif // RPLEXPR_HPP diff --git a/rplstatic/rplstatic.pro b/rplstatic/rplstatic.pro index 9d694f6..ef9e871 100644 --- a/rplstatic/rplstatic.pro +++ b/rplstatic/rplstatic.pro @@ -33,7 +33,8 @@ SOURCES += \ ../rplexpr/rpllexer.cpp \ ../rplexpr/rplsource.cpp \ ../rplcore/rplqstring.cpp \ - ../rplexpr/rplastree.cpp + ../rplexpr/rplastree.cpp \ + ../rplexpr/rplasclasses.cpp HEADERS += ../rplmodules.hpp \ ../rplcore/rplconfig.hpp \ @@ -58,7 +59,8 @@ HEADERS += ../rplmodules.hpp \ ../rplexpr/rplexpr.hpp \ ../rplexpr/rplsource.hpp \ ../rplcore/rplqstring.hpp \ - ../rplexpr/rplastree.hpp + ../rplexpr/rplastree.hpp \ + ../rplexpr/rplasclasses.hpp unix:!symbian { maemo5 { diff --git a/unittests/unittests.pro b/unittests/unittests.pro index ca425c5..61f3e81 100644 --- a/unittests/unittests.pro +++ b/unittests/unittests.pro @@ -31,5 +31,6 @@ SOURCES += main.cpp \ rplsource_test.cpp \ rpllexer_test.cpp \ rplqstring_test.cpp \ - ../rplcore/rplqstring.cpp + ../rplcore/rplqstring.cpp \ + ../rplexpr/rplasclasses.cpp -- 2.39.5