delete it.value();
}
}
+
+/**
+ * @brief Search the class in the symbol space hierarchy.
+ *
+ * @param name Name of the class
+ * @return NULL: not found<br>
+ * otherwise: the class
+ */
+RplASClass*RplSymbolSpace::findClass(const QString& name) const
+{
+ return NULL;
+}
/**
* @brief Returns the name of the symbol space.
*
* @brief RplASException::RplASException
* @param message
*/
+
+
+/**
+ * @brief Builds the message.
+ *
+ * @param position describes the position of the error/warning
+ * @param format the reason of the exception
+ * @param varList the values for the placeholders in the format.
+ */
+void RplASException::build(const RplSourcePosition* position,
+ const char* format, va_list varList)
+{
+ char buffer[64000];
+ if (position != NULL)
+ m_message = position->toString().toUtf8();
+ vsnprintf(buffer, sizeof buffer, format, varList);
+ m_message += buffer;
+}
+
/**
* @brief Constructor.
*
const char* format, ...) :
RplException("")
{
- char buffer[64000];
- if (position != NULL)
- m_message = position->toString().toUtf8();
va_list ap;
va_start(ap, format);
- vsnprintf(buffer, sizeof buffer, format, ap);
+ build(position, format, ap);
va_end(ap);
- m_message += buffer;
}
+/**
+ * @brief Builds the message.
+ *
+ * @param position describes the position of the error/warning
+ * @param format the reason of the exception
+ * @param varList the values for the placeholders in the format.
+ */
+RplASException::RplASException() :
+ RplException("")
+{
+}
/** @class RplASVariant rplastree.hpp "rplexpr/rplastree.hpp"
*
rc.sprintf("%f", m_value.m_float);
break;
case DT_INTEGER:
- rc.sprintf("%d", m_value.m_float);
+ rc.sprintf("%d", m_value.m_int);
break;
case DT_OBJECT:
m_class->toString(m_value.m_object, maxLength);
delete m_child2;
m_child2 = NULL;
}
+RplASItem* RplASNode2::child2() const
+{
+ return m_child2;
+}
+
+void RplASNode2::setChild2(RplASItem* child2)
+{
+ m_child2 = child2;
+}
+
/** @class RplASNode3 rplastree.hpp "rplexpr/rplastree.hpp"
*
}
/**
- * @brief Returns the method.
- *
- * @return the method
+ * @brief Constructor.
*/
-RplASMethod* RplAsMethodCall::method() const
+RplASMethodCall::RplASMethodCall() :
+ RplASNode2(AST_METHOD_CALL),
+ RplASStatement()
+{
+
+}
+
+RplASMethodCall::~RplASMethodCall()
+{
+
+}
+
+void RplASMethodCall::execute()
+{
+}
+
+RplASMethod* RplASMethodCall::method() const
{
return m_method;
}
* @brief Sets the method.
* @param method method to set
*/
-void RplAsMethodCall::setMethod(RplASMethod* method)
+void RplASMethodCall::setMethod(RplASMethod* method)
{
m_method = method;
}
*
* @return the first element of an argument list
*/
-RplArgument* RplAsMethodCall::arg1() const
+RplASArgument* RplASMethodCall::arg1() const
{
return m_arg1;
}
*
* @param arg1 NULL or the first element of the argument list
*/
-void RplAsMethodCall::setArg1(RplArgument* arg1)
+void RplASMethodCall::setArg1(RplASArgument* arg1)
{
m_arg1 = arg1;
}
+
+RplASBinaryOp::RplASBinaryOp() :
+ RplASNode2(AST_BINARY_OP),
+ m_operator(0)
+{
+}
+
+int RplASBinaryOp::getOperator() const
+{
+ return m_operator;
+}
+
+void RplASBinaryOp::setOperator(int op)
+{
+ m_operator = op;
+}
class RplASException : public RplException {
public:
+ RplASException();
RplASException(const RplSourcePosition* position, const char* message, ...);
+protected:
+ void build(const RplSourcePosition* position, const char* format, va_list varList);
};
class RplASClass;
public:
RplASNode2(RplASItemType type);
virtual ~RplASNode2();
+public:
+ RplASItem* child2() const;
+ void setChild2(RplASItem* child2);
+
protected:
RplASItem* m_child2;
};
{
public:
RplASBinaryOp();
+public:
+ int getOperator() const;
+ void setOperator(int op);
+
private:
int m_operator;
};
virtual ~RplASWhile();
};
-class RplArgument : public RplASNode2, public RplASStatement
+class RplASArgument : public RplASNode2, public RplASStatement
{
public:
- RplArgument();
- virtual ~RplArgument();
+ RplASArgument();
+ virtual ~RplASArgument();
};
class RplASMethod;
-class RplAsMethodCall : public RplASNode2, public RplASStatement
+class RplASMethodCall : public RplASNode2, public RplASStatement
{
public:
- RplAsMethodCall();
- virtual ~RplAsMethodCall();
+ RplASMethodCall();
+ virtual ~RplASMethodCall();
+public:
+ virtual void execute();
+
public:
RplASMethod* method() const;
void setMethod(RplASMethod* method);
- RplArgument* arg1() const;
- void setArg1(RplArgument* arg1);
+ RplASArgument* arg1() const;
+ void setArg1(RplASArgument* arg1);
private:
RplASMethod* m_method;
- RplArgument* m_arg1;
+ RplASArgument* m_arg1;
};
class RplParameter : RplASItem
void finishClassOrMethod(const QString& name);
SymbolSpaceStack& symbolSpaces();
RplSymbolSpace* currentSpace() const;
+ RplASClass* findClass(const QString& name);
private:
// the mother of all symbol spaces.
#include "rplexpr/rpllexer.hpp"
#include "rplexpr/rplastree.hpp"
#include "rplexpr/rplvm.hpp"
+#include "rplexpr/rplparser.hpp"
#include "rplexpr/rplmfparser.hpp"
#endif // RPLEXPR_HPP
m_input.remove(0, length);
m_currentCol += length;
}
+/**
+ * @brief Returns the current position.
+ *
+ * @return the current source code position
+ */
+RplSourcePosition* RplLexer::currentPosition() const
+{
+ return m_currentPosition;
+}
/**
* @brief Returns the next token.
void startUnit(const QString& unit);
RplSource* source();
int prioOfOp(int op) const;
+ RplSourcePosition* currentPosition() const;
+
private:
void prepareOperators(const char* operators);
void initializeComments(const char* comments);
#include "rplcore/rplcore.hpp"
#include "rplexpr/rplexpr.hpp"
+enum MFLocations{
+ L_PARSE_OPERAND_RPARENTH = 2000,
+ L_PARSE_OPERAND_RPARENTH_FUNC,
+ L_PARSE_OPERAND_WRONG
+
+};
+
/** @class RplMFParser rpllexer.hpp "rplexpr/rplmfparser.hpp"
*
* @brief Implements a parser for the language MF.
*/
RplMFParser::RplMFParser(RplSource& source, RplASTree& abstractSyntaxTree) :
+ RplParser(m_lexer, abstractSyntaxTree),
m_lexer(&source,
MF_KEYWORDS, MF_OPERATORS,
"/* */ // \n",
"a-zA-Z_", "a-zA-Z0-9_",
- RplLexer::NUMTYPE_ALL, RplLexer::SF_LIKE_C),
- m_tree(abstractSyntaxTree)
+ RplLexer::NUMTYPE_ALL, RplLexer::SF_LIKE_C)
{
}
/**
* @brief Parses a function or a generator.
*/
-void RplMFParser::parseFunc()
+RplASItem* RplMFParser::parseFunc()
{
-
+ RplASItem*rc = NULL;
+ return rc;
}
/**
* @brief Parses an if statement.
*/
-void RplMFParser::parseIf()
+RplASItem* RplMFParser::parseIf()
{
-
+ RplASItem*rc = NULL;
+ return rc;
}
/**
* @brief Parses a while statement.
*/
-void RplMFParser::parseWhile()
+RplASItem* RplMFParser::parseWhile()
{
-
+ RplASItem*rc = NULL;
+ return rc;
}
/**
* @brief Parses a repeat statement.
*/
-void RplMFParser::parseRepeat()
+RplASItem* RplMFParser::parseRepeat()
{
-
+ RplASItem*rc = NULL;
+ return rc;
}
/**
* @brief Parses a for statement.
*/
-void RplMFParser::parseFor()
+RplASItem* RplMFParser::parseFor()
{
-
+ RplASItem*rc = NULL;
+ return rc;
}
/**
* @param clazz NULL or the type of the variable
* @param attribute 0 or attribute of the variable: K_CONST or K_LAZY
*/
-void RplMFParser::parseDefinition(RplASClass* clazz, Keyword attribute)
+RplASItem* RplMFParser::parseDefinition(RplASClass* clazz, Keyword attribute)
{
-
+ RplASItem*rc = NULL;
+ return rc;
}
/**
RplASItem* RplMFParser::parseOperand(int level)
{
RplToken* token = m_lexer.nextNonSpaceToken();
+ RplSourcePosition* startPosition = m_lexer.currentPosition();
RplASItem* rc = NULL;
switch(token->tokenType()){
case TOKEN_OPERATOR:
- rc = new RplASUnary(token->id());
- rc->setChild(parseOperand);
+ {
+ Operator op = (Operator) token->id();
+ if (op == O_LPARENTH){
+ rc = parseTerm(level + 1);
+ } else if (IS_UNARY_OP(op)){
+ RplASUnaryOp* node = new RplASUnaryOp(token->id(), AST_PRE_UNARY_OP);
+ rc = node;
+ node->setChild(parseOperand(level));
+ token = m_lexer.nextNonSpaceToken();
+ if(token->tokenType() != TOKEN_OPERATOR || token->id() != O_RPARENT){
+ QByteArray pos = startPosition->toString().toUtf8();
+ // this call never comes back (exception!)
+ syntaxError(L_PARSE_OPERAND_RPARENTH,
+ "')' expected. '(' is at %s", pos.constData());
+ }
+ }
break;
+ }
case TOKEN_STRING:
case TOKEN_NUMBER:
case TOKEN_REAL:
{
- RplASConstant constant = new RplASConstant();
- item = constant;
+ RplASConstant* constant = new RplASConstant();
+ rc = constant;
switch(token->tokenType()){
case TOKEN_STRING:
- constant.m_value.setString(token->toString());
+ constant->value().setString(token->toString());
break;
case TOKEN_NUMBER:
- constant.m_value.setInt(token->asInteger());
+ constant->value().setInt(token->asInteger());
break;
case TOKEN_REAL:
- constant.m_value.setFloat(token->asReal());
+ constant->value().setFloat(token->asReal());
break;
default:
break;
{
QString name = token->toString();
token = m_lexer.nextNonSpaceToken();
+ startPosition = m_lexer.currentPosition();
if (token->tokenType() != TOKEN_OPERATOR){
RplASNamedValue* var = new RplASNamedValue(name);
- item = var;
+ rc = var;
m_lexer.undoLastToken();
} else {
if (token->id() == O_LPARENTH){
- RplASItem* args = parseArguments();
- RplAsMethodCall node = new RplAsMethodCall();
- node.setArg1(args);
+ RplASArgument* args = parseArguments();
+ RplASMethodCall* call = new RplASMethodCall();
+ rc = call;
+ call->setArg1(args);
+ token = m_lexer.nextNonSpaceToken();
+ if (token->tokenType() != TOKEN_OPERATOR
+ || token->id() != O_RPARENT){
+ QByteArray pos = startPosition->toString().toUtf8();
+ // this call never comes back (exception!)
+ syntaxError(L_PARSE_OPERAND_RPARENTH_FUNC,
+ "')' expected. '(' is at %s", pos.constData());
+ }
+ } else if (token->id() == O_LBRACKET){
+
} else if (token->id() == O_INC || token->id() == O_DEC){
RplASNamedValue* var = new RplASNamedValue(name);
- item = var;
+ rc = var;
}
}
break;
}
default:
+ // this call never comes back (exception!)
+ syntaxError(L_PARSE_OPERAND_WRONG,
+ "unexpected symbol detected. Operand expected");
break;
}
- return item;
+ return rc;
}
/**
*/
RplASItem* RplMFParser::parseTerm(int depth){
RplToken* token;
- RplSourcePosition* start = m_lexer.currentSourcePosition();
+ RplSourcePosition* start = m_lexer.currentPosition();
RplASItem* top = NULL;
RplASItem* item;
int lastPrio = -1;
bool again = true;
do {
- item = parseOperand(level);
+ item = parseOperand(depth);
token = m_lexer.nextNonSpaceToken();
RplTokenType tokenType = token->tokenType();
switch(tokenType){
{
if (IS_BINARY_OP(tokenType)){
RplASBinaryOp* op = new RplASBinaryOp();
- op->setOp(token->id());
+ op->setOperator(token->id());
int prio = m_lexer.prioOfOp(token->id());
op->setChild(item);
op->setPosition(m_lexer.currentPosition());
- op->setChild2(parseOperand(level));
- if
+ op->setChild2(parseOperand(depth));
+
}
break;
}
case TOKEN_REAL:
break;
case TOKEN_KEYWORD:
- case TOKEN_OPERATOR:
case TOKEN_ID:
case TOKEN_END_OF_SOURCE:
again = false;
* @brief Parses an expression.
*
* @precond the nextNonSpaceToken() will return the first token of the expr.
- * @postcond all tokens belonging to the expr are read
+ * @postcond all tokens belonging to the expr are read (not more!)
*
- * @return the token behind the expr
+ * @return the tree of the expression
*/
-RplToken* RplMFParser::parseExpr()
+RplASItem* RplMFParser::parseExpr()
{
- RplASItem* item = parseTerm(0);
+ RplASItem* rc = parseTerm(0);
+ return rc;
}
/**
*
* A body is a module, a class region or a method body.
*/
-void RplMFParser::parseBody()
+RplASItem* RplMFParser::parseBody()
{
- RplToken token = m_lexer.nextNonSpaceToken();
- switch(token.tokenType())
+ 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.undoNextToken();
- token = parseExpr();
+ m_lexer.undoLastToken();
+ item = parseExpr();
break;
case TOKEN_KEYWORD:
- switch (token.id()){
+ switch (token->id()){
case K_IF:
- parseIf();
+ item = parseIf();
break;
case K_WHILE:
- parseWhile();
+ item = parseWhile();
break;
case K_REPEAT:
- parseRepeat();
+ item = parseRepeat();
break;
case K_FOR:
- parseFor();
+ item = parseFor();
break;
case K_CLASS:
- parseClass();
+ item = parseClass();
break;
case K_FUNCTION:
case K_GENERATOR:
- parseMethod();
+ item = parseMethodDefinition();
break;
case K_IMPORT:
parseImport();
break;
case K_CONST:
case K_LAZY:
- parseDefinition(NULL, token.id());
+ item = parseDefinition(NULL, (Keyword) token->id());
break;
case K_INT:
- parseDefinition(&RplASInteger.m_instance);
+ item = parseDefinition(&RplASInteger::m_instance, K_UNDEF);
break;
case K_FLOAT:
- parseDefinition(&RplASFloat.m_instance);
+ parseDefinition(&RplASFloat::m_instance, K_UNDEF);
break;
case K_BOOL:
- parseDefinition(&RplASBoolean.m_instance);
+ parseDefinition(&RplASBoolean::m_instance, K_UNDEF);
break;
default:
break;
break;
case TOKEN_ID:
{
- RplASClass* clazz = m_tree.currentSpace()->findClass();
+ RplASClass* clazz = m_tree.currentSpace()->findClass(token->toString());
if (clazz != NULL){
- parseDefinition(clazz);
+ item = parseDefinition(clazz, K_UNDEF);
} else {
- m_lexer.undoNextToken();
- parseExpr();
+ m_lexer.undoLastToken();
+ item = parseExpr();
}
break;
}
default:
break;
}
+ //@ToDo: add item to list
+ return NULL;
+}
+
+/**
+ * @brief Parses a class definition.
+ * @return the node in an abstract syntax tree
+ */
+RplASItem*RplMFParser::parseMethodDefinition()
+{
+ RplASItem* rc = NULL;
+ return rc;
+}
+
+/**
+ * @brief Parses a class definition.
+ * @return the node in an abstract syntax tree
+ */
+RplASItem*RplMFParser::parseClass()
+{
+ RplASItem* rc = NULL;
+ return rc;
+}
+
+/**
+ * @brief Parses a the import statement
+ */
+void RplMFParser::parseImport()
+{
+
}
/**
*
* @param name the name of the module (without path)
*/
-void RplMFParser::parseModule(const QString& name)
+RplASItem* RplMFParser::parseModule(const QString& name)
{
m_tree.startModule(name);
parseBody();
}
+/**
+ * @brief Parses an argument list.
+ * @return the first element of the argument list
+ */
+RplASArgument*RplMFParser::parseArguments()
+{
+
+}
+
#ifndef RPLMFPARSER_HPP
#define RPLMFPARSER_HPP
-class RplMFParser
+class RplMFParser : public RplParser
{
public:
enum Keyword {
public:
RplMFParser(RplSource& source, RplASTree& ast);
public:
- void parseFunc();
- void parseIf();
- void parseWhile();
- void parseRepeat();
- void parseFor();
- void parseDefinition(RplASClass* clazz, Keyword attribute);
- RplToken* parseExpr();
- void parseBody();
- void parseClass();
- void parseModule(const QString& name);
+ RplASItem* parseFunc();
+ RplASItem* parseIf();
+ RplASItem* parseWhile();
+ RplASItem* parseRepeat();
+ RplASItem* parseFor();
+ RplASItem* parseDefinition(RplASClass* clazz, Keyword attribute);
+ RplASItem* parseExpr();
+ RplASItem* parseBody();
+ RplASItem* parseMethodDefinition();
+ RplASItem* parseClass();
+ void parseImport();
+ RplASItem* parseModule(const QString& name);
void parse();
+protected:
+ RplASArgument* parseArguments();
RplASItem* parseOperand(int level);
RplASItem* parseTerm(int depth);
private:
RplLexer m_lexer;
- RplASTree& m_tree;
};
#endif // RPLMFPARSER_HPP
--- /dev/null
+/*
+ * 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 RplSyntaxError rplparser.hpp "rplexpr/rplparser.hpp"
+ *
+ * @brief Implements an exception used for jumping out from many nested calls.
+ *
+ * We don't want to cancel the parse process if an syntax error has been
+ * occurred. Therefore we want to recreate after it.
+ * A relative simple solution:
+ * Ignoring the rest of the statement and start again with the next statement.
+ * Often the detection is done deep in an expression and we must jump out.
+ * This allows this exception.
+ */
+
+/**
+ * @brief Constructor.
+ * @param reason the reason of the exception
+ * @return
+ */
+RplSyntaxError::RplSyntaxError(const char* reason) :
+ m_reason(reason)
+{
+}
+
+/** @class RplParserStop rplparser.hpp "rplexpr/rplparser.hpp"
+ *
+ * @brief Implements an exception used for jumping out from many nested calls.
+ *
+ * In some situation we want to abort the parsing process.
+ * This exception allows this without high costs even the abort position
+ * is in a deep nested call.
+ */
+
+/**
+ * @brief Constructor.
+ * @param reason the reason of the exception
+ * @return
+ */
+RplParserStop::RplParserStop(const char* reason) :
+ RplSyntaxError(reason)
+{
+}
+
+/** @class RplParser rplparser.hpp "rplexpr/rplparser.hpp"
+ *
+ * @brief Implements a base class for parsers.
+ *
+ * This class offers common things for all parsers, e.g. error handling.
+ */
+/**
+ * @brief Constructor.
+ *
+ * @param lexer the tokenizer
+ * @param tree the abstract syntax tree
+ */
+RplParser::RplParser(RplLexer& lexer, RplASTree& tree) :
+ m_lexer(lexer),
+ m_tree(tree),
+ m_messages(),
+ m_errors(0),
+ m_warnings(0),
+ m_maxErrors(20),
+ m_maxWarnings(20)
+{
+}
+
+/**
+ * @brief Common actions for the error/warning functions.
+ *
+ * @param prefix first char in the message: 'E' (error) or 'W' (warning)
+ * @param location unique id of the error/warning message
+ * @param format message with placeholdes like sprintf()
+ * @param varList the variable argument list
+ */
+void RplParser::addMessage(char prefix, int location, const char* format,
+ va_list varList){
+ char buffer[2048];
+ QString msg;
+ RplSourcePosition* pos = m_lexer.currentPosition();
+ snprintf(buffer, sizeof buffer, "%c%04d %s:%d-%d: ", prefix, location,
+ pos->sourceUnit()->name().toUtf8().constData(),
+ pos->lineNo(), pos->column());
+ int length = strlen(buffer);
+ vsnprintf(buffer + length, -length + sizeof buffer, format, varList);
+ m_messages.append(buffer);
+}
+
+/**
+ * @brief Adds an error message and throws an exception.
+ *
+ * The exception will be catched at a position where error recovery can take place.
+ *
+ * @param location unique id of the error/warning message
+ * @param format message with placeholdes like sprintf()
+ * @param ... optional: the variable argument list
+ */
+
+void RplParser::syntaxError(int location, const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ addMessage('E', location, format, ap);
+ va_end(ap);
+ throw RplSyntaxError(format);
+}
+
+/**
+ * @brief Adds an error message.
+ *
+ * If too much errors an exception will be thrown to stop parsing.
+ *
+ * @param location unique id of the error/warning message
+ * @param format message with placeholdes like sprintf()
+ * @param ... optional: the variable argument list
+ */
+void RplParser::error(int location, const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ addMessage('E', location, format, ap);
+ va_end(ap);
+ if (++m_errors >= m_maxErrors)
+ throw RplParserStop("too many errors");
+}
+
+/**
+ * @brief Adds a warning message.
+ *
+ * If too much warnings an exception will be thrown to stop parsing.
+ *
+ * @param location unique id of the error/warning message
+ * @param format message with placeholdes like sprintf()
+ * @param ... optional: the variable argument list
+ */
+void RplParser::warning(int location, const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ addMessage('W', location, format, ap);
+ va_end(ap);
+ if (++m_warnings >= m_maxWarnings)
+ throw RplParserStop("too many warnings");
+}
+
+
--- /dev/null
+/*
+ * 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 RPLPARSER_HPP
+#define RPLPARSER_HPP
+
+class RplSyntaxError
+{
+public:
+ RplSyntaxError(const char* reason);
+private:
+ const char* m_reason;
+};
+
+class RplParserStop : public RplSyntaxError {
+public:
+ RplParserStop(const char* reason);
+};
+
+class RplParser {
+public:
+ typedef QList<QString> MessageList;
+public:
+ RplParser(RplLexer& lexer, RplASTree& ast);
+public:
+ void syntaxError(int location, const char* format, ...);
+ void error(int location, const char* format, ...);
+ void warning(int location, const char* format, ...);
+protected:
+ void addMessage(char prefix, int location, const char* format, va_list varList);
+
+protected:
+ RplLexer m_lexer;
+ RplASTree& m_tree;
+ MessageList m_messages;
+ int m_errors;
+ int m_warnings;
+ int m_maxErrors;
+ int m_maxWarnings;
+};
+
+#endif // RPLPARSER_HPP
return rc;
}
+/**
+ * @brief Returns the line number.
+ * @return the line number
+ */
+int RplSourcePosition::lineNo() const
+{
+ return m_lineNo;
+}
+
/**
* @brief Sets the line number.
*
../rplexpr/rplastree.cpp \
../rplexpr/rplasclasses.cpp \
../rplexpr/rplmfparser.cpp \
- ../rplexpr/rplvm.cpp
+ ../rplexpr/rplvm.cpp \
+ ../rplexpr/rplparser.cpp
HEADERS += ../rplmodules.hpp \
../rplcore/rplconfig.hpp \
../rplexpr/rplastree.hpp \
../rplexpr/rplasclasses.hpp \
../rplexpr/rplmfparser.hpp \
- ../rplexpr/rplvm.hpp
+ ../rplexpr/rplvm.hpp \
+ ../rplexpr/rplparser.hpp
unix:!symbian {
maemo5 {
}
virtual void doIt(void) {
+ baseTest();
}
};
void testRplMFParser() {
../rplexpr/rplsource.cpp \
../rplexpr/rpllexer.cpp \
../rplexpr/rplastree.cpp \
+ ../rplexpr/rplparser.cpp \
../rplexpr/rplmfparser.cpp \
rplexception_test.cpp \
rplstring_test.cpp \