]> gitweb.hamatoma.de Git - reqt/commitdiff
day's work
authorhama <hama@siduction.net>
Thu, 3 Jul 2014 22:11:27 +0000 (00:11 +0200)
committerhama <hama@siduction.net>
Thu, 3 Jul 2014 22:11:27 +0000 (00:11 +0200)
rplexpr/rplastree.cpp
rplexpr/rplastree.hpp
rplexpr/rpllexer.cpp
rplexpr/rpllexer.hpp
rplexpr/rplmfparser.cpp

index 49724606747b38bbe4099052027314c068ebcf82..bef3477af4d50281cdfe2cb2838b32e062f237ab 100644 (file)
@@ -614,7 +614,6 @@ void RplASExprStatement::execute()
  */
 void RplASExprStatement::calc(RplASVariant& value)
 {
-
 }
 
 /**
@@ -730,6 +729,26 @@ RplASNode3::~RplASNode3()
     delete m_child3;
     m_child3 = NULL;
 }
+/**
+ * @brief Returns the child3.
+ *
+ * @return  the child 3
+ */
+RplASItem* RplASNode3::child3() const
+{
+    return m_child3;
+}
+
+/**
+ * @brief Sets the child3.
+ *
+ * @param child3    the new child3
+ */
+void RplASNode3::setChild3(RplASItem* child3)
+{
+    m_child3 = child3;
+}
+
 
 /** @class RplASNode4 rplastree.hpp "rplexpr/rplastree.hpp"
  *
@@ -757,6 +776,73 @@ RplASNode4::~RplASNode4()
     m_child4 = NULL;
 }
 
+/**
+ * @brief Returns the child4.
+ *
+ * @return  the child 4
+ */
+RplASItem* RplASNode4::child4() const
+{
+    return m_child4;
+}
+
+/**
+ * @brief Sets the child4.
+ *
+ * @param child4    the new child3
+ */
+void RplASNode4::setChild4(RplASItem* child4)
+{
+    m_child4 = child4;
+}
+
+
+/** @class RplASNode5 rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements a inner node of the abstract syntax tree with 4 childs.
+ *
+ * This class is an abstract class.
+ */
+
+/**
+ * @brief RplASNode5::RplASNode5
+ * @param type
+ */
+RplASNode5::RplASNode5(RplASItemType type) :
+    RplASNode4(type),
+    m_child5(NULL)
+{
+}
+
+/**
+ * @brief Destructor.
+ */
+RplASNode5::~RplASNode5()
+{
+    delete m_child5;
+    m_child5 = NULL;
+}
+
+/**
+ * @brief Returns the child5.
+ *
+ * @return  the child 5
+ */
+RplASItem* RplASNode5::child5() const
+{
+    return m_child5;
+}
+
+/**
+ * @brief Sets the child5.
+ *
+ * @param child5    the new child3
+ */
+void RplASNode5::setChild5(RplASItem* child5)
+{
+    m_child5 = child5;
+}
+
 /** @class RplASUnaryOp rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a unary operation.
@@ -909,6 +995,67 @@ void RplASCondition::dump(FILE* fp, int indent)
         m_child->dump(fp, indent);
 }
 
+/** @class RplASIf rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements an if statement.
+ *
+ * The if statement has a condition, a then-part and an optional else-part.
+ * If the condition is evaluated to true, the then-part will be executed.
+ * Otherwise the else-part if it exists.
+ */
+
+RplASIf::RplASIf() :
+    RplASNode3(AST_IF)
+{
+}
+
+/**
+ * @brief Executes the statement.
+ *
+ * Meaning of the childs:
+ * m_child: condition
+ * m_child2: if-part
+ * m_child3: else-part
+ */
+void RplASIf::execute()
+{
+    RplASCondition* condition = dynamic_cast<RplASCondition*>(m_child);
+    if (condition == NULL)
+        throw RplASException(m_child == NULL ? m_position : m_child->position(),
+                             "if statement: not a condition");
+    RplASStatement* body = NULL;
+    if(condition->calcAsBool()){
+        body = dynamic_cast<RplASStatement*>(m_child2);
+        if (body == NULL)
+            throw RplASException(m_child2 == NULL ? m_position : m_child2->position(),
+                                 "if statement: then-part is not a statement");
+    } else if (m_child2 != NULL){
+        body = dynamic_cast<RplASStatement*>(m_child3);
+        if (body == NULL)
+            throw RplASException(m_child3->position(),
+                                 "if statement: else-part is not a statement");
+    }
+    body->execute();
+}
+
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASIf::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sIf id: %d condition: %d then: %d else: %d\n", tabs,
+            m_id, m_child->id(), m_child2->id(),
+            m_child3 == NULL ? 0 : m_child3->id());
+    m_child->dump(fp, indent + 1);
+    m_child2->dump(fp, indent + 1);
+    if (m_child3 != NULL)
+        m_child3->dump(fp, indent + 1);
+}
+
 /** @class RplASFor rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a for statement.
@@ -928,12 +1075,6 @@ RplASFor::RplASFor() :
     RplASStatement()
 {
 }
-/**
- * @brief Destructor.
- */
-RplASFor::~RplASFor()
-{
-}
 
 /**
  * @brief Executes the statement.
@@ -965,6 +1106,100 @@ void RplASFor::execute()
     }
 }
 
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASFor::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sfor id: %d condition: %d then: %d else: %d\n", tabs,
+            m_id, m_child->id(), m_child2->id(),
+            m_child3 == NULL ? 0 : m_child3->id());
+    m_child->dump(fp, indent + 1);
+    m_child2->dump(fp, indent + 1);
+    if (m_child3 != NULL)
+        m_child3->dump(fp, indent + 1);
+}
+
+/** @class RplASForCounted rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements a for statement.
+ *
+ * The for statement has an optional variable, an optional start value,
+ * an end value, an optional step and a body.
+ *
+ * The start and end value will be calculated.
+ * The body will be executed so many times given by the start and end value.
+ */
+
+/**
+ * @brief Constructor.
+ */
+RplASForCounted::RplASForCounted() :
+    RplASNode5(AST_FOR),
+    RplASStatement()
+{
+}
+
+/**
+ * @brief Executes the statement.
+ *
+ * Meaning of the childs:
+ * m_child: body
+ * m_child2: variable
+ * m_child3: start value
+ * m_child4: end value
+ * m_child5: step value
+ */
+void RplASForCounted::execute()
+{
+    RplASStatement* body = dynamic_cast<RplASStatement*>(m_child);
+    if (body == NULL)
+        throw RplASException(m_child == NULL ? m_position : m_child->position(),
+                             "forc statement: body is not a statement");
+    int start = 1;
+    int step = 1;
+    int end = 0;
+    RplASNamedValue* var = NULL;
+    if (m_child2 != NULL){
+        var = dynamic_cast<RplASNamedValue*>(m_child2);
+    }
+    for(int ii = start; ii <= end; ii++){
+        body->execute();
+    }
+}
+
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASForCounted::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%sforc id: %d var: %d from: %d to: %d step: %d body: %d\n",
+            tabs, m_id,
+            m_child2 == NULL ? 0 : m_child2->id(),
+            m_child3 == NULL ? 0 : m_child3->id(),
+            m_child4 == NULL ? 0 : m_child4->id(),
+            m_child5 == NULL ? 0 : m_child5->id(),
+            m_child == NULL ? 0 : m_child->id());
+    if (m_child2 != NULL)
+        m_child2->dump(fp, indent + 1);
+    if (m_child3 != NULL)
+        m_child3->dump(fp, indent + 1);
+    if (m_child4 != NULL)
+        m_child4->dump(fp, indent + 1);
+    if (m_child5 != NULL)
+        m_child5->dump(fp, indent + 1);
+    if (m_child != NULL)
+        m_child->dump(fp, indent + 1);
+}
+
 /** @class RplASWhile rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a while statement.
@@ -978,12 +1213,101 @@ RplASWhile::RplASWhile() :
     RplASStatement()
 {
 }
+
 /**
- * @brief Destructor.
+ * @brief Executes the statement.
+ *
+ * Meaning of the childs:
+ * m_child: body
+ * m_child2: condition
+ */
+void RplASWhile::execute()
+{
+    RplASStatement* body = dynamic_cast<RplASStatement*>(m_child);
+    if (body == NULL)
+        throw RplASException(m_child == NULL ? m_position : m_child->position(),
+                             "while statement: body is not a statement");
+    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");
+    while(condition->calcAsBool()){
+        body->execute();
+    }
+}
+
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
+ */
+void RplASWhile::dump(FILE* fp, int indent)
+{
+    DEFINE_TABS(indent);
+    fprintf(fp, "%swhile id: %d condition: %d body: %d\n", tabs, m_id,
+            m_child2 == NULL ? 0 : m_child2->id(),
+            m_child == NULL ? 0 : m_child->id());
+    if (m_child2 != NULL)
+        m_child2->dump(fp, indent + 1);
+    if (m_child != NULL)
+        m_child->dump(fp, indent + 1);
+}
+
+/** @class RplASRepeat rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements a while statement.
+ *
+ * The while statement has an a condition and a body.
+ * The body will be executed while the condition returns true.
+ */
+
+RplASRepeat::RplASRepeat() :
+    RplASNode2(AST_REPEAT),
+    RplASStatement()
+{
+}
+
+/**
+ * @brief Executes the statement.
+ *
+ * Meaning of the childs:
+ * m_child: body
+ * m_child2: condition
+ */
+void RplASRepeat::execute()
+{
+    RplASStatement* body = dynamic_cast<RplASStatement*>(m_child);
+    if (body == NULL)
+        throw RplASException(m_child == NULL ? m_position : m_child->position(),
+                             "while statement: body is not a statement");
+    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");
+    do {
+        body->execute();
+    } while(condition->calcAsBool());
+}
+
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp        target file
+ * @param indent    nesting level
  */
-RplASWhile::~RplASWhile()
+void RplASRepeat::dump(FILE* fp, int indent)
 {
+    DEFINE_TABS(indent);
+    fprintf(fp, "%srepeat id: %d condition: %d body: %d\n", tabs, m_id,
+            m_child2 == NULL ? 0 : m_child2->id(),
+            m_child == NULL ? 0 : m_child->id());
+    if (m_child2 != NULL)
+        m_child2->dump(fp, indent + 1);
+    if (m_child != NULL)
+        m_child->dump(fp, indent + 1);
 }
+
 /** @class RplASClass rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements the base class of a Abstract Syntax Tree class.
@@ -1404,8 +1728,9 @@ void RplASMethod::dump(FILE* fp, int indent)
  * @brief constructor
  */
 RplASArgument::RplASArgument() :
-    RplASNode2(AST_ARGUMENT),
-    RplASStatement()
+    RplASNode2(AST_ARGUMENT)
 {
 }
 
+
+
index 7c64dcc84c063eb4d204a0e49095164646a4c819..d8b6f9c8e3b1b4ca60159b91c0f84dea4037dc96 100644 (file)
@@ -24,6 +24,7 @@ enum RplASItemType {
     AST_BINARY_OP,
     AST_METHOD_CALL,
     AST_WHILE,
+    AST_REPEAT,
     AST_IF,
     AST_CONDITION,
     AST_FOR,
@@ -187,6 +188,10 @@ class RplASNode3 : public RplASNode2
 public:
     RplASNode3(RplASItemType type);
     virtual ~RplASNode3();
+public:
+    RplASItem* child3() const;
+    void setChild3(RplASItem* child3);
+
 protected:
     RplASItem* m_child3;
 };
@@ -196,10 +201,26 @@ class RplASNode4 : public RplASNode3
 public:
     RplASNode4(RplASItemType type);
     virtual ~RplASNode4();
+public:
+    RplASItem* child4() const;
+    void setChild4(RplASItem* child4);
+
 protected:
     RplASItem* m_child4;
 };
 
+class RplASNode5 : public RplASNode4
+{
+public:
+    RplASNode5(RplASItemType type);
+    virtual ~RplASNode5();
+public:
+    RplASItem*child5() const;
+    void setChild5(RplASItem* child5);
+protected:
+    RplASItem* m_child5;
+};
+
 class RplASNamedValue : public RplASNode1, public RplASCalculable
 {
 public:
@@ -298,23 +319,52 @@ public:
     void dump(FILE* fp, int indent);
 };
 
+class RplASIf : public RplASNode3, public RplASStatement
+{
+public:
+    RplASIf();
+public:
+    virtual void execute();
+    virtual void dump(FILE* fp, int indent);
+};
+
 class RplASFor : public RplASNode4, public RplASStatement
 {
 public:
     RplASFor();
-    virtual ~RplASFor();
 public:
     virtual void execute();
+    virtual void dump(FILE* fp, int indent);
+};
+
+class RplASForCounted : public RplASNode5, public RplASStatement
+{
+public:
+    RplASForCounted();
+public:
+    virtual void execute();
+    virtual void dump(FILE* fp, int indent);
 };
 
 class RplASWhile : public RplASNode2, public RplASStatement
 {
 public:
     RplASWhile();
-    virtual ~RplASWhile();
+public:
+    virtual void execute();
+    virtual void dump(FILE* fp, int indent);
+};
+
+class RplASRepeat : public RplASNode2, public RplASStatement
+{
+public:
+    RplASRepeat();
+public:
+    virtual void execute();
+    virtual void dump(FILE* fp, int indent);
 };
 
-class RplASArgument : public RplASNode2, public RplASStatement
+class RplASArgument : public RplASNode2
 {
 public:
     RplASArgument();
index a13b0113feb365cbba16e526aff97d32fd198bb0..1ab955e3cda9d7d43452f450abe1726965c8af39 100644 (file)
@@ -187,9 +187,10 @@ bool RplToken::isTokenType(RplTokenType expected) const
 /**
  * @brief Checks whether the instance is a given operator.
  *
- * @param expected  the token type to compare
+ * @param expected      the expected operator
+ * @param alternative   0 or a second possibility
  *
- * @return  true: the instance is an operator and the expected<br>
+ * @return  true: the instance is an operator and the expected or the alternative<br>
  *          false: otherwise
  */
 bool RplToken::isOperator(int expected, int alternative) const
@@ -198,6 +199,22 @@ bool RplToken::isOperator(int expected, int alternative) const
                                              || m_value.m_id == alternative);
 }
 
+/**
+ * @brief Checks whether the instance is a given keyword.
+ *
+ * @param expected      the expected keyword
+ * @param alternative   0 or a second possibility
+ *
+ * @return  true: the instance is a keyword and the expected or the alternative<br>
+ *          false: otherwise
+ */
+
+bool RplToken::isKeyword(int expected, int alternative) const
+{
+    return m_tokenType == TOKEN_KEYWORD && (m_value.m_id == expected
+                                             || m_value.m_id == alternative);
+}
+
 /**
  * @brief Makes all members undefined.
  */
index d11720b71108b411eb59950a92ab93fc957b3355..20e24ab31458902cdb6be67e7361e5103c92dff6 100644 (file)
@@ -52,6 +52,7 @@ public:
     RplTokenType tokenType() const;
     bool isTokenType(RplTokenType expected) const;
     bool isOperator(int expected, int alternative = 0) const;
+    bool isKeyword(int expected, int alternative = 0) const;
     void clear();
     bool isCapitalizedId() const;
 protected:
index bf2268dc32f47579803ada7b49849d28bb1e1f27..b179fa2c2d857079c754ef6280652baca4bdc1aa 100644 (file)
@@ -21,7 +21,14 @@ enum MFLocations{
     L_DEFINITION_UNKNOWN_CLASS,
     L_DEFINITION_MISSING_ID,
     L_DEFINITION_NO_OP      = 2010,
-    L_DEFINITION_NO_SEMICOLON
+    L_DEFINITION_NO_SEMICOLON,
+    L_PARSE_IF_NO_THEN,
+    L_PARSE_IF_NO_ELSE,
+    L_PARSE_IF_NO_FI,
+    L_PARSE_WHILE_NO_DO     = 2015,
+    L_PARSE_WHILE_NO_OD,
+    L_PARSE_REPEAT_NO_UNTIL,
+    L_PARSE_REPEAT_NO_SEMI
 
 };
 
@@ -57,7 +64,23 @@ RplASItem* RplMFParser::parseFunc()
  */
 RplASItem* RplMFParser::parseIf()
 {
-    RplASItem*rc = NULL;
+    RplASIf* rc = new RplASIf();
+    rc->setPosition(m_lexer.currentPosition());
+
+    RplASItem* condition = parseExpr();
+    if (! m_lexer.currentToken()->isKeyword(K_THEN))
+        syntaxError(L_PARSE_IF_NO_THEN, "'then' expected");
+    rc->setChild(condition);
+    RplASItem* body = parseBody();
+    rc->setChild2(body);
+    if (! m_lexer.currentToken()->isKeyword(K_ELSE, K_FI))
+        syntaxError(L_PARSE_IF_NO_ELSE, "'else' or 'fi' expected");
+    if ( m_lexer.currentToken()->isKeyword(K_ELSE)){
+        RplASItem* body = parseBody();
+        rc->setChild3(body);
+    }
+    if (! m_lexer.currentToken()->isKeyword(K_FI))
+        syntaxError(L_PARSE_IF_NO_FI, "'fi' expected");
     return rc;
 }
 /**
@@ -66,7 +89,17 @@ RplASItem* RplMFParser::parseIf()
 
 RplASItem* RplMFParser::parseWhile()
 {
-    RplASItem*rc = NULL;
+    RplASWhile* rc = new RplASWhile();
+    rc->setPosition(m_lexer.currentPosition());
+
+    RplASItem* condition = parseExpr();
+    if (! m_lexer.currentToken()->isKeyword(K_DO))
+        syntaxError(L_PARSE_WHILE_NO_DO, "'do' expected");
+    rc->setChild2(condition);
+    RplASItem* body = parseBody();
+    rc->setChild(body);
+    if (! m_lexer.currentToken()->isKeyword(K_OD))
+        syntaxError(L_PARSE_WHILE_NO_OD, "'od'  expected");
     return rc;
 }
 
@@ -75,7 +108,18 @@ RplASItem* RplMFParser::parseWhile()
  */
 RplASItem* RplMFParser::parseRepeat()
 {
-    RplASItem*rc = NULL;
+    RplASRepeat* rc = new RplASRepeat();
+    rc->setPosition(m_lexer.currentPosition());
+
+    RplASItem* body = parseBody();
+    rc->setChild(body);
+    if (! m_lexer.currentToken()->isKeyword(K_UNTIL))
+        syntaxError(L_PARSE_REPEAT_NO_UNTIL, "'until'  expected");
+
+    RplASItem* condition = parseExpr();
+    if (! m_lexer.currentToken()->isOperator(O_SEMICOLON))
+        syntaxError(L_PARSE_REPEAT_NO_SEMI, "';' expected");
+    rc->setChild2(condition);
     return rc;
 }