From e1e67108320bd8cb5f19a488dd30aadfeefbb73c Mon Sep 17 00:00:00 2001 From: hama Date: Wed, 3 Sep 2014 23:32:17 +0200 Subject: [PATCH] dayly work --- rplexpr/rplastree.cpp | 700 +++++++++++++++--- rplexpr/rplastree.hpp | 96 ++- rplexpr/rplmfparser.cpp | 11 +- rplexpr/rplparser.cpp | 35 +- rplexpr/rplparser.hpp | 11 +- rplexpr/rplvm.cpp | 39 + rplexpr/rplvm.hpp | 6 + test/{rplmfparser => mfparser}/baseTest.txt | 0 test/{rplmfparser => mfparser}/field1.txt | 0 test/{rplmfparser => mfparser}/forC1.txt | 0 test/{rplmfparser => mfparser}/forC2.txt | 0 test/{rplmfparser => mfparser}/forIt1.txt | 0 test/{rplmfparser => mfparser}/ifTest1.txt | 0 test/{rplmfparser => mfparser}/ifTest2.txt | 0 test/{rplmfparser => mfparser}/list1.txt | 0 test/{rplmfparser => mfparser}/list2.txt | 0 test/mfparser/main1.txt | 26 + test/{rplmfparser => mfparser}/map1.txt | 0 test/{rplmfparser => mfparser}/map2.txt | 0 test/{rplmfparser => mfparser}/meth1.txt | 0 test/{rplmfparser => mfparser}/meth2.txt | 0 test/{rplmfparser => mfparser}/meth3.txt | 0 test/{rplmfparser => mfparser}/meth4.txt | 0 test/{rplmfparser => mfparser}/methc1.txt | 0 test/{rplmfparser => mfparser}/opTest1.txt | 0 test/{rplmfparser => mfparser}/repeatTest.txt | 0 test/{rplmfparser => mfparser}/string1.mf | 0 test/{rplmfparser => mfparser}/string1.txt | 0 test/{rplmfparser => mfparser}/varDefTest.txt | 0 test/{rplmfparser => mfparser}/whileTest.txt | 0 unittests/rplmfparser_test.cpp | 11 +- unittests/rplvm_test.cpp | 1 + 32 files changed, 810 insertions(+), 126 deletions(-) rename test/{rplmfparser => mfparser}/baseTest.txt (100%) rename test/{rplmfparser => mfparser}/field1.txt (100%) rename test/{rplmfparser => mfparser}/forC1.txt (100%) rename test/{rplmfparser => mfparser}/forC2.txt (100%) rename test/{rplmfparser => mfparser}/forIt1.txt (100%) rename test/{rplmfparser => mfparser}/ifTest1.txt (100%) rename test/{rplmfparser => mfparser}/ifTest2.txt (100%) rename test/{rplmfparser => mfparser}/list1.txt (100%) rename test/{rplmfparser => mfparser}/list2.txt (100%) create mode 100644 test/mfparser/main1.txt rename test/{rplmfparser => mfparser}/map1.txt (100%) rename test/{rplmfparser => mfparser}/map2.txt (100%) rename test/{rplmfparser => mfparser}/meth1.txt (100%) rename test/{rplmfparser => mfparser}/meth2.txt (100%) rename test/{rplmfparser => mfparser}/meth3.txt (100%) rename test/{rplmfparser => mfparser}/meth4.txt (100%) rename test/{rplmfparser => mfparser}/methc1.txt (100%) rename test/{rplmfparser => mfparser}/opTest1.txt (100%) rename test/{rplmfparser => mfparser}/repeatTest.txt (100%) rename test/{rplmfparser => mfparser}/string1.mf (100%) rename test/{rplmfparser => mfparser}/string1.txt (100%) rename test/{rplmfparser => mfparser}/varDefTest.txt (100%) rename test/{rplmfparser => mfparser}/whileTest.txt (100%) diff --git a/rplexpr/rplastree.cpp b/rplexpr/rplastree.cpp index 3db6a3e..b1d1cda 100644 --- a/rplexpr/rplastree.cpp +++ b/rplexpr/rplastree.cpp @@ -21,23 +21,30 @@ enum { LOC_VARDEF_EXEC_1 = RPL_FIRST_OF(RPL_MODULE_ASTREE), // 11001 - LOC_UNOP_1, - LOC_UNOP_2, - LOC_UNOP_3, - LOC_UNOP_4, // 10005 + LOC_UNOP_CALC_1, + LOC_UNARY_CHECK_1, + LOC_UNARY_CHECK_2, + LOC_UNARY_CHECK_3, // 11005 LOC_BINOP_1, LOC_BINOP_CALC_1, LOC_BINOP_CALC_2, LOC_BINOP_CALC_3, - LOC_BINOP_CALC_4, + LOC_BINOP_CALC_4, // 11010 LOC_BINOP_CALC_5, LOC_BINOP_CALC_6, LOC_BINOP_CALC_7, LOC_BINOP_CALC_8, - LOC_BINOP_CALC_9, + LOC_BINOP_CALC_9, // 11015 LOC_BINOP_CALC_10, LOC_BINOP_CALC_11, LOC_BINOP_CALC_12, + LOC_VARDEF_CHECK_1, + LOC_VARDEF_CHECK_2, // 11020 + LOC_CONV_CHECK_1, + LOC_CONV_CHECK_2, + LOC_CONV_TRY_1, + LOC_ITEM_FORCE_ERROR_1, + LOC_UNARY_CHECK_4, // 11025 LOC_COUNT }; @@ -686,12 +693,86 @@ void RplASItem::setFlags(int flags) m_flags = flags; } +/** + * @brief Tests the compatibility of 2 data types. + * @param class1 1st class to inspect + * @param class2 2nd class to inspect + * @return true: classes are compatible
+ * false: otherwise + */ +bool RplASItem::typeCheck(RplASClass* class1, RplASClass* class2){ + bool rc; + if (class1 == NULL || class2 == NULL) + rc = false; + else + //@ToDo: subclasses + rc = class1 == class2; + return rc; +} + +/** + * @brief Issues an error message. + * + * @param location an error specific id + * @param parser for error processing + * @param format the error message with placeholders (like printf) + * @param ... the values for the placeholders + * @return false (for chaining) + */ +bool RplASItem::error(int location, RplParser& parser, const char* format, ...) +{ + va_list varList; + va_start(varList, format); + parser.addMessage(RplParser::LT_ERROR, location, m_position, format, varList); + va_end(varList); + return false; +} + +/** + * @brief Ensures the occurrence of an error. + * + * When called a previous error should be happend. If not an internal error + * will be issued. + * + * @param parser for error processing + * @return false (for chaining) + */ +bool RplASItem::ensureError(RplParser& parser) +{ + if (parser.errors() == 0) + error(LOC_ITEM_FORCE_ERROR_1, parser, "lost error (internal error)"); + return false; +} /** @class RplASCalculable rplastree.hpp "rplexpr/rplastree.hpp" * * @brief An abstract base class for items which calculates a value. * */ +/** + * @brief Constructor. + */ +RplASCalculable::RplASCalculable() : + m_class(NULL) +{ +} +/** + * @brief Returns the class of the node + * @return the class + */ + +RplASClass* RplASCalculable::clazz() const +{ + return m_class; +} +/** + * @brief Sets the class of the node. + * @param clazz the new class + */ +void RplASCalculable::setClass(RplASClass* clazz) +{ + m_class = clazz; +} /** @class RplASStorable rplastree.hpp "rplexpr/rplastree.hpp" * @@ -726,6 +807,17 @@ void RplASConstant::calc(RplVMThread& thread) value.copyValue(m_value); } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: a constant is always correct + */ +bool RplASConstant::check(RplParser& parser) +{ + return true; +} + /** * @brief Writes the internals into a file. * @@ -793,6 +885,17 @@ void RplASListConstant::calc(RplVMThread& thread) value.copyValue(m_value); } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: a constant is always correct + */ +bool RplASListConstant::check(RplParser& parser) +{ + return true; +} + /** * @brief Writes the internals into a file. * @@ -850,6 +953,17 @@ void RplASMapConstant::calc(RplVMThread& thread) RplASVariant& value = thread.reserveValue(); value.copyValue(m_value); } + +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: a constant is always correct + */ +bool RplASMapConstant::check(RplParser& parser) +{ + return true; +} /** * @brief Writes the internals into a file. * @@ -908,7 +1022,6 @@ RplASNamedValue::RplASNamedValue(RplASClass* dataType,RplSymbolSpace* space, RplASNode1(AST_NAMED_VALUE), m_name(name), m_attributes(attributes), - m_dataType(dataType), m_symbolSpace(space), m_variableNo(-1) { @@ -943,6 +1056,18 @@ void RplASNamedValue::calc(RplVMThread& thread) { thread.valueToTop(m_symbolSpace, m_variableNo); } + +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASNamedValue::check(RplParser& parser) +{ + return true; +} /** * @brief Writes the internals into a file. * @@ -956,25 +1081,6 @@ void RplASNamedValue::dump(RplWriter& writer, int indent) m_name.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; -} - -/** - * @brief Assigns the top of stack of the thread to the instance. - * - * @param thread the execution unit, a virtual machine thread - */ -void RplASNamedValue::assign(RplVMThread& thread) -{ - -} /** * @brief Returns the symbol space of the variable. @@ -1007,11 +1113,170 @@ int RplASNamedValue::variableNo() const return m_variableNo; } +/** @class RplASConversion rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements a data type conversion. + * + * m_child: the expression which will be converted + */ +/** + * @brief Constructor. + * @param expression the expression to convert + */ +RplASConversion::RplASConversion(RplASItem* expression) : + RplASNode1(AST_CONVERSION), + m_conversion(C_UNDEF) +{ + m_child = expression; + m_position = expression->position(); +} + +/** + * @brief Convert an expression to another data type. + * + * Possible conversions: @see RplASConversion::Conversion + * + * @param thread execution value + */ +void RplASConversion::calc(RplVMThread& thread) +{ + RplASCalculable* expr = dynamic_cast(m_child); + expr->calc(thread); + RplASVariant& value = thread.topOfValues(); + switch(m_conversion){ + case C_INT_TO_FLOAT: + value.setFloat((qreal) value.asInt()); + break; + case C_FLOAT_TO_INT: + value.setInt((int) value.asFloat()); + break; + case C_BOOL_TO_INT: + value.setInt((int) value.asBool()); + break; + case C_BOOL_TO_FLOAT: + value.setFloat((qreal) value.asBool()); + break; + default: + break; + } +} + +/** + * @brief Returns the conversion type of two classes. + * + * @param from class to convert + * @param to result class of the conversion + * + * @return C_UNDEF: not convertable
+ * otherwise: the conversion type + */ +RplASConversion::Conversion RplASConversion::findConversion(RplASClass* from, + RplASClass* to) +{ + Conversion rc = C_UNDEF; + if (from == RplASFloat::m_instance){ + if (to == RplASInteger::m_instance) + rc = C_FLOAT_TO_INT; + } else if (from == RplASInteger::m_instance){ + if (to == RplASFloat::m_instance) + rc = C_INT_TO_FLOAT; + } else if (from == RplASBoolean::m_instance){ + if (to == RplASInteger::m_instance) + rc = C_BOOL_TO_INT; + else if (to == RplASInteger::m_instance) + rc = C_BOOL_TO_INT; + else if (to == RplASFloat::m_instance) + rc = C_BOOL_TO_FLOAT; + } + return rc; +} + +/** + * @brief Checks the node. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASConversion::check(RplParser& parser) +{ + bool rc = false; + RplASCalculable* expr = dynamic_cast(m_child); + if (expr == NULL){ + parser.error(LOC_CONV_CHECK_1, "missing expr"); + } else { + RplASClass* from = expr->clazz(); + rc = m_child->check(parser); + if (rc){ + m_conversion = findConversion(from, m_class); + if (m_conversion != C_UNDEF) + rc = true; + else + parser.error(LOC_CONV_CHECK_2, + "invalid data type conversion: %s -> %s", + from->name().constData(), + m_class->name().constData()); + } + } + return rc; +} + +/** + * @brief Writes the internals into a file. + * + * @param writer writes to output + * @param indent nesting level + */ +void RplASConversion::dump(RplWriter& writer, int indent) +{ + char buffer[256]; + writer.formatIndented(indent, "conversion %s id: %d expr: %d %s", + m_class->name().constData(), m_id, m_child->id(), + positionStr(buffer, sizeof buffer)); +} + +/** + * @brief Tries to find a conversion to a given type. + * + * Checks if an expression has a given type. If not it will be tried to find + * a conversion. If this is not possible an error occurres. Otherwise the + * converter will be returned. + * + * @param expected the expected data type + * @param expr the expression to convert + * @param parser for error processing + * + * @return NULL: no conversion necessary
+ * otherwise: a converter to the given type + */ +RplASConversion* RplASConversion::tryConversion(RplASClass* expected, + RplASItem* expr, RplParser& parser) +{ + RplASConversion* rc = NULL; + if (expr->check(parser)){ + RplASCalculable* expr2 = dynamic_cast(expr); + if (expr2 != NULL){ + Conversion type = findConversion(expr2->clazz(), expected); + if (type == C_UNDEF){ + parser.error(LOC_CONV_TRY_1, + "invalid data type conversion: %s -> %s", + expr2->clazz()->name().constData(), + expected->name().constData()); + } else if (expr2->clazz() != expected){ + rc = new RplASConversion(expr); + rc->m_conversion = type; + rc->setClass(expected); + } + } + } + return rc; +} + /** @class RplASIndexedValue rplastree.hpp "rplexpr/rplastree.hpp" * * @brief Implements an indexed values (member of a list) * - * m_child: the parent: a list expression + * m_child: the parent: a list/map expression * m_child2: the index expression */ RplASIndexedValue::RplASIndexedValue() : @@ -1019,6 +1284,32 @@ RplASIndexedValue::RplASIndexedValue() : { } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASIndexedValue::check(RplParser& parser) +{ + bool rc = false; + RplASCalculable* list = dynamic_cast(m_child); + if (list == NULL) + throw RplASException(m_position, "indexed value: empty list"); + m_child->check(parser); + RplASConversion* converter = RplASConversion::tryConversion( + RplASInteger::m_instance, m_child, parser); + if (converter == NULL){ + RplASClass* clazz = list->clazz(); + rc = clazz != NULL && clazz == RplASInteger::m_instance; + } else { + m_child = converter; + rc = true; + } + return rc; +} + /** * @brief Writes the internals into an output media. * @@ -1070,9 +1361,9 @@ void RplASVarDefinition::dump(RplWriter& writer, int indent) if (m_endOfScope > 0) qsnprintf(endOfScope, sizeof endOfScope, "-%d:0", m_endOfScope); char buffer[256]; - writer.formatIndented(indent, "varDef %s %s id: %d namedValue: %d value: %d succ: %d %s%s", - namedValue == NULL || namedValue->dataType() == NULL - ? "?" : namedValue->dataType()->name().constData(), + writer.formatIndented(indent, + "varDef %s %s id: %d namedValue: %d value: %d succ: %d %s%s", + clazz() == NULL ? "?" : clazz()->name().constData(), name.constData(), m_id, m_child2 == NULL ? 0 : m_child2->id(), m_child3 == NULL ? 0 : m_child3->id(), @@ -1101,10 +1392,10 @@ const QByteArray& RplASVarDefinition::name() const * * @return the data type */ -RplASClass* RplASVarDefinition::datatype() const +RplASClass* RplASVarDefinition::clazz() const { RplASNamedValue* namedValue = dynamic_cast(m_child2); - RplASClass* rc = namedValue->dataType(); + RplASClass* rc = namedValue == NULL ? NULL : namedValue->clazz(); return rc; } /** @@ -1131,28 +1422,58 @@ void RplASVarDefinition::setEndOfScope(int endOfScope) /** - * @brief Executes the statement. + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise */ -void RplASVarDefinition::execute(RplVMThread& thread) +bool RplASVarDefinition::check(RplParser& parser) { + bool rc = false; if (m_child3 != NULL){ RplASNamedValue* var = dynamic_cast(m_child2); if (var == NULL) - error(thread.logger(), LOC_VARDEF_EXEC_1, - "Not a named value: id: %d", + error(LOC_VARDEF_CHECK_1, parser, "Not a named value: id: %d", m_child2 == NULL ? 0 : m_child2->id()); else{ - RplASCalculable* expr = dynamic_cast(m_child3); - if (expr == NULL) - error(thread.logger(), LOC_VARDEF_EXEC_1, - "not calculable: id: %d", - m_child3 == NULL ? 0 : m_child2->id()); + if (m_child3 == NULL) + // no initialization: + rc = true; else { - expr->calc(thread); - var->assign(thread); + rc = m_child3->check(parser); + if (rc){ + RplASCalculable* expr = dynamic_cast(m_child3); + if (! typeCheck(var->clazz(), expr->clazz())) + rc = error(LOC_VARDEF_CHECK_2, parser, + "data types are not compatible: %s/%s", + var->clazz()->name().constData(), + expr->clazz() == NULL ? "?" + : expr->clazz()->name().constData()); + } } } } + return rc; +} + +/** + * @brief Executes the statement. + */ +void RplASVarDefinition::execute(RplVMThread& thread) +{ + RplASNamedValue* var = dynamic_cast(m_child2); + RplASCalculable* expr = dynamic_cast(m_child3); + expr->calc(thread); + RplASVariant& value = thread.popValue(); + RplASVariant& destination = thread.valueOfVariable( + var->m_symbolSpace, var->m_variableNo); + if (thread.tracing()) + thread.vm()->traceWriter()->format("%s = %.80s [%.80s]", + var->m_name.constData(), + value.toString().constData(), + destination.toString().constData()); + destination.copyValue(value); } /** @class RplASExprStatement rplastree.hpp "rplexpr/rplastree.hpp" @@ -1173,12 +1494,30 @@ RplASExprStatement::RplASExprStatement() : m_flags |= NF_STATEMENT; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASExprStatement::check(RplParser& parser) +{ + bool rc = m_child2->check(parser); + RplASCalculable* expr = dynamic_cast (m_child2); + if (expr == NULL) + rc = false; + return rc; +} /** * @brief Executes the statement. */ void RplASExprStatement::execute(RplVMThread& thread) { - + RplASCalculable* expr = dynamic_cast (m_child2); + expr->calc(thread); + RplASVariant& value = thread.popValue(); + value.destroyValue(); } /** @@ -1240,6 +1579,8 @@ RplASItem* RplASNode1::child() const */ void RplASNode1::setChild(RplASItem* child) { + if (child->id() == 2) + m_child = child; m_child = child; } @@ -1486,7 +1827,9 @@ void RplASNode6::setChild6(RplASItem* child6) * * @brief Implements an unary operation. * - * This is an operation with one operand, e.g. the boolean not operation. + * This is an operation with one operand, e.g. the boolean 'not' operation. + * + * m_child: operand */ /** @@ -1512,60 +1855,83 @@ void RplASUnaryOp::calc(RplVMThread& thread) switch(m_operator){ case UOP_PLUS: break; - case UOP_MINUS: - switch (value.variantType()){ - case RplASVariant::VT_FLOAT: - value.setFloat(- value.asFloat()); - break; - case RplASVariant::VT_INTEGER: - value.setInt(- value.asInt()); - break; - case RplASVariant::VT_BOOL: - case RplASVariant::VT_OBJECT: - default: - error(thread.logger(), LOC_UNOP_1, "wrong type %s for '-'", - value.nameOfType()); - break; - } + case UOP_MINUS_INT: + value.setInt(- value.asInt()); break; - case UOP_LOGICAL_NOT: - switch (value.variantType()){ - case RplASVariant::VT_FLOAT: - value.setBool(value.asFloat() != 0.0); - break; - case RplASVariant::VT_INTEGER: - value.setBool(value.asInt() != 0); - break; - case RplASVariant::VT_BOOL: - value.setBool(! value.asBool()); - break; - case RplASVariant::VT_OBJECT: - default: - error(thread.logger(), LOC_UNOP_2, "wrong type %s for '!'", - value.nameOfType()); - break; - } + case UOP_MINUS_FLOAT: + value.setFloat(- value.asFloat()); break; - case UOP_BIT_NOT: - switch (value.variantType()){ - case RplASVariant::VT_INTEGER: - value.setInt(~value.asInt()); - break; - case RplASVariant::VT_FLOAT: - case RplASVariant::VT_BOOL: - case RplASVariant::VT_OBJECT: - default: - error(thread.logger(), LOC_UNOP_3, "wrong type %s for '~'", - value.nameOfType()); - break; - } + case UOP_NOT_BOOL: + value.setBool(! value.asBool()); + break; + case UOP_NOT_INT: + value.setInt(~value.asInt()); break; + case UOP_DEC: + case UOP_INC: default: - error(thread.logger(), LOC_UNOP_4, "unknown operator: %d", m_operator); + error(thread.logger(), LOC_UNOP_CALC_1, "unknown operator: %d", m_operator); break; } } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASUnaryOp::check(RplParser& parser) +{ + bool rc = m_child->check(parser); + if (rc){ + RplASCalculable* expr = dynamic_cast(m_child); + RplASClass* clazz = expr == NULL ? NULL : expr->clazz(); + if (clazz == NULL){ + rc = ensureError(parser); + } else { + switch(m_operator){ + case UOP_PLUS: + if (clazz != RplASInteger::m_instance + && clazz != RplASFloat::m_instance) + rc = error(LOC_UNARY_CHECK_1, parser, + "wrong data type for unary operator '+': %s", + clazz->name().constData()); + break; + case UOP_MINUS_INT: + if (clazz != RplASFloat::m_instance) + m_operator = UOP_MINUS_FLOAT; + else if (clazz != RplASInteger::m_instance) + rc = error(LOC_UNARY_CHECK_2, parser, + "wrong data type for unary operator '-': %s", + clazz->name().constData()); + break; + case UOP_NOT_BOOL: + if (clazz != RplASBoolean::m_instance) + rc = error(LOC_UNARY_CHECK_3, parser, + "wrong data type for unary operator '!': %s", + clazz->name().constData()); + break; + case UOP_NOT_INT: + if (clazz != RplASInteger::m_instance) + rc = error(LOC_UNARY_CHECK_4, parser, + "wrong data type for unary operator '!': %s", + clazz->name().constData()); + break; + case UOP_DEC: + break; + case UOP_INC: + break; + default: + throw RplASException(position(), "unknown operator: %d", m_operator); + break; + } + } + } + return rc; +} + /** * @brief Returns the operator of the unary operation. * @@ -1597,7 +1963,7 @@ void RplASUnaryOp::dump(RplWriter& writer, int indent) /** * @brief Returns the name (a string) of an unary operator. * - * @param op the op to convert + * @param op the operand to convert * @return the name of the operator */ const char*RplASUnaryOp::nameOfOp(RplASUnaryOp::UnaryOp op) @@ -1607,13 +1973,14 @@ const char*RplASUnaryOp::nameOfOp(RplASUnaryOp::UnaryOp op) case UOP_PLUS: rc="+"; break; - case UOP_MINUS: + case UOP_MINUS_INT: + case UOP_MINUS_FLOAT: rc="-"; break; - case UOP_LOGICAL_NOT: + case UOP_NOT_BOOL: rc="!"; break; - case UOP_BIT_NOT: + case UOP_NOT_INT: rc="~"; break; case UOP_INC: @@ -1674,6 +2041,18 @@ void RplASCondition::calc(RplVMThread& thread) throw RplASException(m_position, "child of condition is not calculable"); node->calc(thread); } + +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASCondition::check(RplParser& parser) +{ + return false; +} /** * @brief Calculates the boolean value and returns it. */ @@ -1735,6 +2114,18 @@ RplASIf::RplASIf() : m_flags |= NF_STATEMENT; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASIf::check(RplParser& parser) +{ + return false; +} + /** * @brief Executes the statement. * @@ -1813,6 +2204,18 @@ RplASForIterated::RplASForIterated(RplASVarDefinition* variable) : m_child2 = variable; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASForIterated::check(RplParser& parser) +{ + return false; +} + /** * @brief Executes the statement. * @@ -1876,6 +2279,18 @@ RplASForCounted::RplASForCounted(RplASVarDefinition* variable) : m_child3 = variable; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASForCounted::check(RplParser& parser) +{ + return false; +} + /** * @brief Executes the statement. * @@ -1946,6 +2361,18 @@ RplASWhile::RplASWhile() : m_flags |= NF_STATEMENT; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASWhile::check(RplParser& parser) +{ + return false; +} + /** * @brief Executes the statement. * @@ -2006,6 +2433,18 @@ RplASRepeat::RplASRepeat() : m_flags |= NF_STATEMENT; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASRepeat::check(RplParser& parser) +{ + return false; +} + /** * @brief Executes the statement. * @@ -2347,6 +2786,18 @@ RplASMethodCall::RplASMethodCall(const QByteArray& name, RplASItem* parent) : m_child3 = parent; } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASMethodCall::check(RplParser& parser) +{ + return false; +} + /** * @brief Writes the internals into a file. @@ -2603,6 +3054,18 @@ void RplASBinaryOp::calc(RplVMThread& thread) } } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASBinaryOp::check(RplParser& parser) +{ + return false; +} + /** * @brief Returns the operator. * @@ -2837,6 +3300,27 @@ RplASMethod::RplASMethod(const QByteArray& name, RplASTree& tree) : { } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASMethod::check(RplParser& parser) +{ + return false; +} + +/** + * @brief Executes the statement. + * + * This method will be never called. Must exit: Otherwise the class is abstract. + */ +void RplASMethod::execute(RplVMThread& thread) +{ +} + /** * @brief Writes the internals of the instance into a file. @@ -2908,7 +3392,7 @@ bool RplASMethod::equalSignature(RplASMethod& other) const else { RplASVarDefinition* def = dynamic_cast(args->child2()); RplASVarDefinition* defOther = dynamic_cast(otherArgs->child2()); - if (def->datatype() != defOther->datatype()) + if (def->clazz() != defOther->clazz()) rc = false; } } @@ -2950,6 +3434,18 @@ RplASArgument::RplASArgument() : { } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASArgument::check(RplParser& parser) +{ + return false; +} + /** * @brief Writes the internals of the instance into a file. * @@ -3000,6 +3496,18 @@ RplASField::RplASField(const QByteArray& name) : { } +/** + * @brief Checks the correctness of the instance. + * + * @param parser for error processing + * @return true: node is correct
+ * false: otherwise + */ +bool RplASField::check(RplParser& parser) +{ + return false; +} + /** * @brief Writes the internals of the instance into a file. * diff --git a/rplexpr/rplastree.hpp b/rplexpr/rplastree.hpp index 96492a5..a12554e 100644 --- a/rplexpr/rplastree.hpp +++ b/rplexpr/rplastree.hpp @@ -18,6 +18,7 @@ enum RplASItemType { AST_MAP_CONSTANT, AST_MAP_ENTRY, AST_NAMED_VALUE, + AST_CONVERSION, AST_INDEXED_VALUE, AST_FIELD, AST_VAR_DEFINITION, @@ -110,6 +111,7 @@ private: }; class RplASTree; +class RplParser; class RplASItem { public: @@ -129,6 +131,8 @@ public: friend class RplASTree; RplASItem(RplASItemType type); virtual ~RplASItem(); +public: + virtual bool check(RplParser& parser) = 0; public: const RplSourcePosition* position() const; void setPosition(const RplSourcePosition* position); @@ -151,6 +155,9 @@ public: int flags() const; void setFlags(int flags); + bool typeCheck(RplASClass* clazz1, RplASClass* clazz2); + bool error(int location, RplParser& parser, const char* format, ...); + bool ensureError(RplParser& parser); protected: unsigned int m_id:16; RplASItemType m_nodeType:8; @@ -165,12 +172,19 @@ class RplASNode1; class RplVMThread; class RplASCalculable { +public: + RplASCalculable(); public: virtual void calc(RplVMThread& thread) = 0; +public: + RplASClass* clazz() const; + void setClass(RplASClass* clazz); +protected: + RplASClass* m_class; }; class RplStackFrame; -class RplASStorable : RplASCalculable { +class RplASStorable : public RplASCalculable { }; class RplVMThread; class RplASConstant : public RplASItem, public RplASCalculable @@ -179,6 +193,7 @@ public: RplASConstant(); public: virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); public: virtual void dump(RplWriter& writer,int indent); RplASVariant& value(); @@ -272,6 +287,8 @@ public: RplASListConstant(); public: virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); + public: virtual void dump(RplWriter& writer,int indent); RplASVariant& value(); @@ -285,6 +302,7 @@ public: RplASMapConstant(); public: virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); public: virtual void dump(RplWriter& writer,int indent); RplASVariant& value(); @@ -296,6 +314,7 @@ private: class RplSymbolSpace; class RplASNamedValue : public RplASNode1, public RplASStorable { + friend class RplASVarDefinition; public: enum Attributes { A_NONE, @@ -316,27 +335,51 @@ public: public: RplASNamedValue(RplASClass* dataType, RplSymbolSpace* space, const QByteArray& name, int attributes); +public: + virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); public: const QByteArray& name() const; void setSymbolSpace(RplSymbolSpace* space, int variableNo); - virtual void calc(RplVMThread& thread); void dump(RplWriter& writer, int indent); - RplASClass* dataType() const; - void assign(RplVMThread& thread); RplSymbolSpace* symbolSpace() const; int variableNo() const; void setVariableNo(int variableNo); protected: QByteArray m_name; int m_attributes; - RplASClass* m_dataType; RplSymbolSpace* m_symbolSpace; int m_variableNo; }; +class RplASConversion : public RplASNode1, public RplASCalculable { +public: + enum Conversion { + C_UNDEF, + C_INT_TO_FLOAT, + C_FLOAT_TO_INT, + C_BOOL_TO_INT, + C_BOOL_TO_FLOAT + }; + +public: + RplASConversion(RplASItem* expression); +public: + virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); + virtual void dump(RplWriter& writer,int indent); +public: + static RplASConversion* tryConversion(RplASClass* expected, RplASItem* expr, + RplParser& parser); + static Conversion findConversion(RplASClass* from, RplASClass* to); +private: + Conversion m_conversion; +}; class RplASIndexedValue : public RplASNode2 { public: RplASIndexedValue(); +public: + virtual bool check(RplParser& parser); public: void dump(RplWriter& writer, int indent); }; @@ -355,13 +398,14 @@ class RplASVarDefinition : public RplASNode3, public RplASStatement public: RplASVarDefinition(); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); +public: void dump(RplWriter& writer, int indent); const QByteArray& name() const; - RplASClass* datatype() const; int endOfScope() const; void setEndOfScope(int endOfScope); - + RplASClass* clazz() const; private: /// the column of the blockend containing the definition. /// if 0: end is end of method or end of class @@ -374,7 +418,9 @@ class RplASExprStatement : public RplASNode2, public RplASStatement public: RplASExprStatement(); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); +public: void dump(RplWriter& writer, int indent); }; @@ -384,9 +430,10 @@ public: enum UnaryOp { UOP_UNDEF, UOP_PLUS, - UOP_MINUS, - UOP_LOGICAL_NOT, - UOP_BIT_NOT, + UOP_MINUS_INT, + UOP_MINUS_FLOAT, + UOP_NOT_BOOL, + UOP_NOT_INT, UOP_INC, UOP_DEC }; @@ -394,6 +441,8 @@ public: RplASUnaryOp(UnaryOp op, RplASItemType type); public: virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); +public: int getOperator() const; void dump(RplWriter& writer, int indent); public: @@ -453,7 +502,9 @@ private: public: RplASBinaryOp(); public: - void calc(RplVMThread& thread); + virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); +public: BinOperator getOperator() const; void setOperator(BinOperator op); void dump(RplWriter& writer, int indent); @@ -469,7 +520,9 @@ class RplASCondition : public RplASNode1, public RplASCalculable public: RplASCondition(); public: - void calc(RplVMThread& thread); + virtual void calc(RplVMThread& thread); + virtual bool check(RplParser& parser); +public: bool calcAsBool(RplVMThread& thread); void dump(RplWriter& writer, int indent); }; @@ -479,6 +532,7 @@ class RplASIf : public RplASNode4, public RplASStatement public: RplASIf(); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); virtual void dump(RplWriter& writer, int indent); }; @@ -488,6 +542,7 @@ class RplASForIterated : public RplASNode4, public RplASStatement public: RplASForIterated(RplASVarDefinition* variable); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); virtual void dump(RplWriter& writer, int indent); }; @@ -497,6 +552,7 @@ class RplASForCounted : public RplASNode6, public RplASStatement public: RplASForCounted(RplASVarDefinition* variable); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); virtual void dump(RplWriter& writer, int indent); }; @@ -506,6 +562,7 @@ class RplASWhile : public RplASNode3, public RplASStatement public: RplASWhile(); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); virtual void dump(RplWriter& writer, int indent); }; @@ -515,6 +572,7 @@ class RplASRepeat : public RplASNode3, public RplASStatement public: RplASRepeat(); public: + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); virtual void dump(RplWriter& writer, int indent); }; @@ -523,6 +581,8 @@ class RplASArgument : public RplASNode2 { public: RplASArgument(); +public: + virtual bool check(RplParser& parser); public: void dump(RplWriter& writer, int indent); protected: @@ -535,8 +595,10 @@ class RplASMethodCall : public RplASNode3, public RplASStatement public: RplASMethodCall(const QByteArray& name, RplASItem* parent); public: - void dump(RplWriter& writer, int indent); + virtual bool check(RplParser& parser); virtual void execute(RplVMThread& thread); +public: + void dump(RplWriter& writer, int indent); public: RplASMethod* method() const; @@ -562,6 +624,8 @@ class RplASField : public RplASNode1 { public: RplASField(const QByteArray& name); +public: + virtual bool check(RplParser& parser); public: void dump(RplWriter& writer, int indent); private: @@ -576,7 +640,9 @@ class RplASMethod : public RplASNode2 public: RplASMethod(const QByteArray& name, RplASTree& tree); public: - void execute(RplVMThread& thread); + virtual bool check(RplParser& parser); + virtual void execute(RplVMThread& thread); +public: void dump(RplWriter& writer, int indent); RplSymbolSpace* symbols() const; void setSymbols(); @@ -646,6 +712,8 @@ protected: }; #include "rplexpr/rplasclasses.hpp" + +#include "rplparser.hpp" class RplSymbolSpace; class RplASTree { diff --git a/rplexpr/rplmfparser.cpp b/rplexpr/rplmfparser.cpp index 5a2c094..0a7aa99 100644 --- a/rplexpr/rplmfparser.cpp +++ b/rplexpr/rplmfparser.cpp @@ -536,7 +536,7 @@ RplASItem* RplMFParser::buildVarOrField(const QByteArray& name, RplASVarDefinition* var = space->findVariable(name); RplASClass* clazz = NULL; if (var != NULL) - clazz = var->datatype(); + clazz = var->clazz(); RplASNamedValue* var2 = new RplASNamedValue(clazz, space, name, RplASNamedValue::A_NONE); var2->setPosition(position); @@ -564,13 +564,13 @@ RplASUnaryOp::UnaryOp RplMFParser::convertUnaryOp(int op) rc = RplASUnaryOp::UOP_PLUS; break; case O_MINUS: - rc = RplASUnaryOp::UOP_MINUS; + rc = RplASUnaryOp::UOP_MINUS_INT; break; case O_NOT: - rc = RplASUnaryOp::UOP_LOGICAL_NOT; + rc = RplASUnaryOp::UOP_NOT_BOOL; break; case O_BIT_NOT: - rc = RplASUnaryOp::UOP_BIT_NOT; + rc = RplASUnaryOp::UOP_NOT_INT; break; case O_INC: rc = RplASUnaryOp::UOP_INC; @@ -1001,13 +1001,16 @@ RplASItem* RplMFParser::parseBody(Keyword keywordStop, Keyword keywordStop2, break; case K_CLASS: parseClass(); + item = NULL; break; case K_FUNCTION: case K_GENERATOR: parseMethod(); + item = NULL; break; case K_IMPORT: parseImport(); + item = NULL; break; case K_CONST: case K_LAZY: diff --git a/rplexpr/rplparser.cpp b/rplexpr/rplparser.cpp index 477d1dc..de01de5 100644 --- a/rplexpr/rplparser.cpp +++ b/rplexpr/rplparser.cpp @@ -98,8 +98,9 @@ RplParser::RplParser(RplLexer& lexer, RplASTree& tree) : * @param location unique id of the error/warning message * @param position position of the error/warning * @param message message with placeholdes like sprintf() + * @return false (for chaining) */ -void RplParser::addSimpleMessage(LevelTag prefix, int location, +bool RplParser::addSimpleMessage(LevelTag prefix, int location, const RplSourcePosition* position, const char* message){ char buffer[2048]; @@ -114,6 +115,7 @@ void RplParser::addSimpleMessage(LevelTag prefix, int location, memcpy(buffer + used, message, length); buffer[used + length] = '\0'; m_messages.append(buffer); + return false; } /** @@ -124,13 +126,14 @@ void RplParser::addSimpleMessage(LevelTag prefix, int location, * @param position position of the error/warning * @param format message with placeholdes like sprintf() * @param varList the variable argument list + * @return false (for chaining) */ -void RplParser::addMessage(LevelTag prefix, int location, +bool RplParser::addMessage(LevelTag prefix, int location, const RplSourcePosition* position, const char* format, va_list varList){ char buffer[2048]; qvsnprintf(buffer, sizeof buffer, format, varList); - addSimpleMessage(prefix, location, position, buffer); + return addSimpleMessage(prefix, location, position, buffer); } /** @@ -186,8 +189,9 @@ void RplParser::syntaxError(int location, const char* message, * @param location unique id of the error/warning message * @param format message with placeholdes like sprintf() * @param ... optional: the variable argument list + * @return false (for chaining) */ -void RplParser::error(int location, const char* format, ...) +bool RplParser::error(int location, const char* format, ...) { va_list ap; va_start(ap, format); @@ -195,6 +199,7 @@ void RplParser::error(int location, const char* format, ...) va_end(ap); if (++m_errors >= m_maxErrors) throw RplParserStop("too many errors"); + return false; } /** * @brief Adds an error message with an additional info message. @@ -206,14 +211,16 @@ void RplParser::error(int location, const char* format, ...) * @param message describes the error * @param message2 the additional message * @param ... optional: the variable argument list + * @return false (for chaining) */ -void RplParser::error(int location, const RplSourcePosition* position, +bool 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"); + return false; } /** @@ -234,5 +241,23 @@ void RplParser::warning(int location, const char* format, ...) if (++m_warnings >= m_maxWarnings) throw RplParserStop("too many warnings"); } +/** + * @brief Return the number of errors. + * + * @return the count of errors occurred until now + */ +int RplParser::errors() const +{ + return m_errors; +} +/** + * @brief Return the number of warnings. + * + * @return the count of errors occurred until now + */ +int RplParser::warnings() const +{ + return m_warnings; +} diff --git a/rplexpr/rplparser.hpp b/rplexpr/rplparser.hpp index 69a8c7d..cb21c4c 100644 --- a/rplexpr/rplparser.hpp +++ b/rplexpr/rplparser.hpp @@ -38,20 +38,21 @@ public: public: RplParser(RplLexer& lexer, RplASTree& ast); public: - void addSimpleMessage(LevelTag prefix, int location, + bool addSimpleMessage(LevelTag prefix, int location, const RplSourcePosition* pos, const char* message); - void addMessage(LevelTag prefix, int location, + bool addMessage(LevelTag prefix, int location, const RplSourcePosition* pos, const char* format, va_list varList); void syntaxError(int location, const char* message); 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, + bool error(int location, const char* format, ...); + bool error(int location, const RplSourcePosition* position, const char* message, const char* message2); void warning(int location, const char* format, ...); - + int errors() const; + int warnings() const; protected: RplLexer& m_lexer; RplASTree& m_tree; diff --git a/rplexpr/rplvm.cpp b/rplexpr/rplvm.cpp index 828f04b..9598c23 100644 --- a/rplexpr/rplvm.cpp +++ b/rplexpr/rplvm.cpp @@ -127,6 +127,7 @@ RplVMThread::RplVMThread(int maxStack, RplVirtualMachine* vm) : m_id(m_nextId++), m_debugMode(false), m_singleStep(false), + m_tracing(false), m_maxStack(maxStack), m_frameStack(), // the stack is never empty! @@ -300,6 +301,35 @@ RplASVariant& RplVMThread::valueOfVariable(RplSymbolSpace* symbolSpace, return rc; } +/** + * @brief Returns whether each execution step should be dumped. + * @return true: tracing is on
+ * false: otherwise + */ +bool RplVMThread::tracing() const +{ + return m_tracing; +} + +/** + * @brief Sets the tracing flag: if set each execution step is dumped. + * @param tracing true: tracing will be done
+ * false: tracing will not be done + */ +void RplVMThread::setTracing(bool tracing) +{ + m_tracing = tracing; +} + +/** + * @brief Returns the parent, a virtual machine. + * + * @return the virtual machine + */ +RplVirtualMachine* RplVMThread::vm() const +{ + return m_vm; +} /** @class RplVirtualMachine rplvm.hpp "rplexpr/rplvm.hpp" * @@ -403,6 +433,15 @@ void RplVirtualMachine::clearFlag(RplVirtualMachine::VMFlag flag) m_flags &= ~flag; } +/** + * @brief Returns the trace writer. + * @return the trace writer + */ +RplWriter* RplVirtualMachine::traceWriter() const +{ + return m_traceWriter; +} + /** * @brief Sets the trace writer. * diff --git a/rplexpr/rplvm.hpp b/rplexpr/rplvm.hpp index 8109b4f..a22d860 100644 --- a/rplexpr/rplvm.hpp +++ b/rplexpr/rplvm.hpp @@ -52,10 +52,15 @@ public: void valueToTop(RplSymbolSpace* symbolSpace, int variableNo); RplASVariant& lValue(RplASItem* item); RplASVariant& valueOfVariable(RplSymbolSpace* symbolSpace, int variableNo); + bool tracing() const; + void setTracing(bool tracing); + RplVirtualMachine* vm() const; + protected: int m_id; bool m_debugMode; bool m_singleStep; + bool m_tracing; int m_maxStack; StackFrameList m_frameStack; int m_topOfFrames; @@ -89,6 +94,7 @@ public: bool hasFlag(VMFlag flag) const; void setFlag(VMFlag flag); void clearFlag(VMFlag flag); + RplWriter* traceWriter() const; void setTraceWriter(RplWriter* traceWriter); RplASTree& tree() const; diff --git a/test/rplmfparser/baseTest.txt b/test/mfparser/baseTest.txt similarity index 100% rename from test/rplmfparser/baseTest.txt rename to test/mfparser/baseTest.txt diff --git a/test/rplmfparser/field1.txt b/test/mfparser/field1.txt similarity index 100% rename from test/rplmfparser/field1.txt rename to test/mfparser/field1.txt diff --git a/test/rplmfparser/forC1.txt b/test/mfparser/forC1.txt similarity index 100% rename from test/rplmfparser/forC1.txt rename to test/mfparser/forC1.txt diff --git a/test/rplmfparser/forC2.txt b/test/mfparser/forC2.txt similarity index 100% rename from test/rplmfparser/forC2.txt rename to test/mfparser/forC2.txt diff --git a/test/rplmfparser/forIt1.txt b/test/mfparser/forIt1.txt similarity index 100% rename from test/rplmfparser/forIt1.txt rename to test/mfparser/forIt1.txt diff --git a/test/rplmfparser/ifTest1.txt b/test/mfparser/ifTest1.txt similarity index 100% rename from test/rplmfparser/ifTest1.txt rename to test/mfparser/ifTest1.txt diff --git a/test/rplmfparser/ifTest2.txt b/test/mfparser/ifTest2.txt similarity index 100% rename from test/rplmfparser/ifTest2.txt rename to test/mfparser/ifTest2.txt diff --git a/test/rplmfparser/list1.txt b/test/mfparser/list1.txt similarity index 100% rename from test/rplmfparser/list1.txt rename to test/mfparser/list1.txt diff --git a/test/rplmfparser/list2.txt b/test/mfparser/list2.txt similarity index 100% rename from test/rplmfparser/list2.txt rename to test/mfparser/list2.txt diff --git a/test/mfparser/main1.txt b/test/mfparser/main1.txt new file mode 100644 index 0000000..afe940b --- /dev/null +++ b/test/mfparser/main1.txt @@ -0,0 +1,26 @@ +Int a=2+3*4; +func Void main(): +a; +endf += (module) parent: $global +== Methods: +Method main() id: 8 parent: args: 0 body: 10 :1:13 + Expr id: 10 expr: 9 succ: 0 :3:1 + namedValue a id: 9 attr: 0x0 :3:1 + = .main (method) parent: +== Variables: +varDef Int a id: 2 namedValue: 1 value: 4 succ: 0 :1:4 + namedValue a id: 1 attr: 0x0 :1:4 + BinOp id: 4 op: + (17) left: 3 right: 6 :1:7 + const id: 3 value: 2 :1:6 + BinOp id: 6 op: * (19) left: 5 right: 7 :1:9 + const id: 5 value: 3 :1:8 + const id: 7 value: 4 :1:10 +== Body: +varDef Int a id: 2 namedValue: 1 value: 4 succ: 0 :1:4 + namedValue a id: 1 attr: 0x0 :1:4 + BinOp id: 4 op: + (17) left: 3 right: 6 :1:7 + const id: 3 value: 2 :1:6 + BinOp id: 6 op: * (19) left: 5 right: 7 :1:9 + const id: 5 value: 3 :1:8 + const id: 7 value: 4 :1:10 diff --git a/test/rplmfparser/map1.txt b/test/mfparser/map1.txt similarity index 100% rename from test/rplmfparser/map1.txt rename to test/mfparser/map1.txt diff --git a/test/rplmfparser/map2.txt b/test/mfparser/map2.txt similarity index 100% rename from test/rplmfparser/map2.txt rename to test/mfparser/map2.txt diff --git a/test/rplmfparser/meth1.txt b/test/mfparser/meth1.txt similarity index 100% rename from test/rplmfparser/meth1.txt rename to test/mfparser/meth1.txt diff --git a/test/rplmfparser/meth2.txt b/test/mfparser/meth2.txt similarity index 100% rename from test/rplmfparser/meth2.txt rename to test/mfparser/meth2.txt diff --git a/test/rplmfparser/meth3.txt b/test/mfparser/meth3.txt similarity index 100% rename from test/rplmfparser/meth3.txt rename to test/mfparser/meth3.txt diff --git a/test/rplmfparser/meth4.txt b/test/mfparser/meth4.txt similarity index 100% rename from test/rplmfparser/meth4.txt rename to test/mfparser/meth4.txt diff --git a/test/rplmfparser/methc1.txt b/test/mfparser/methc1.txt similarity index 100% rename from test/rplmfparser/methc1.txt rename to test/mfparser/methc1.txt diff --git a/test/rplmfparser/opTest1.txt b/test/mfparser/opTest1.txt similarity index 100% rename from test/rplmfparser/opTest1.txt rename to test/mfparser/opTest1.txt diff --git a/test/rplmfparser/repeatTest.txt b/test/mfparser/repeatTest.txt similarity index 100% rename from test/rplmfparser/repeatTest.txt rename to test/mfparser/repeatTest.txt diff --git a/test/rplmfparser/string1.mf b/test/mfparser/string1.mf similarity index 100% rename from test/rplmfparser/string1.mf rename to test/mfparser/string1.mf diff --git a/test/rplmfparser/string1.txt b/test/mfparser/string1.txt similarity index 100% rename from test/rplmfparser/string1.txt rename to test/mfparser/string1.txt diff --git a/test/rplmfparser/varDefTest.txt b/test/mfparser/varDefTest.txt similarity index 100% rename from test/rplmfparser/varDefTest.txt rename to test/mfparser/varDefTest.txt diff --git a/test/rplmfparser/whileTest.txt b/test/mfparser/whileTest.txt similarity index 100% rename from test/rplmfparser/whileTest.txt rename to test/mfparser/whileTest.txt diff --git a/unittests/rplmfparser_test.cpp b/unittests/rplmfparser_test.cpp index 896566e..6266a48 100644 --- a/unittests/rplmfparser_test.cpp +++ b/unittests/rplmfparser_test.cpp @@ -56,7 +56,7 @@ private: void checkAST(const char* fileExpected, int lineNo){ QByteArray fnExpected = "test"; fnExpected += QDir::separator().toLatin1(); - fnExpected += "rplmfparser"; + fnExpected += "mfparser"; fnExpected += (char) QDir::separator().toLatin1(); fnExpected += fileExpected; QByteArray fnCurrent = getTempFile(fileExpected, "rplmfparser"); @@ -194,9 +194,15 @@ public: parser.parse(); checkAST("meth4.txt", __LINE__); } + void mainTest(){ + setSource("Int a=2+3*4;\nfunc Void main():\na;\nendf"); + RplMFParser parser(m_source, m_tree); + parser.parse(); + checkAST("main1.txt", __LINE__); + } virtual void doIt(void) { - fileClassTest(); + mainTest(); varDefTest(); repeatTest(); baseTest(); @@ -209,6 +215,7 @@ public: forCTest(); listTest(); opTest(); + fileClassTest(); } }; void testRplMFParser() { diff --git a/unittests/rplvm_test.cpp b/unittests/rplvm_test.cpp index 8294491..244058e 100644 --- a/unittests/rplvm_test.cpp +++ b/unittests/rplvm_test.cpp @@ -51,6 +51,7 @@ private: vm.setFlag(RplVirtualMachine::VF_TRACE_STATEMENTS); RplFileWriter writer(fnCurrent); vm.setTraceWriter(&writer); + writer.write(m_currentSource); vm.executeModule(""); assertEqualFiles(fnExpected.constData(), fnCurrent.constData(), __FILE__, lineNo); -- 2.39.5