return ptr != NULL;
}
+/**
+ * @brief Compares two files line by line.
+ *
+ * @param expected the file with the expected content
+ * @param current the file with the current content
+ * @return true: the files are equal<br>
+ * false: otherwise
+ */
+bool RplTest::assertEqualFiles(const char* expected, const char* current,
+ const char* file, int lineNo)
+{
+ bool rc = false;
+ QByteArray expectedContent = RplString::read(expected, true);
+ QByteArray currentContent = RplString::read(current, true);
+ if (expectedContent.isEmpty()){
+ char buffer[512];
+ snprintf(buffer, sizeof buffer, "%s has no content. Does it exist?",
+ expected);
+ error(buffer);
+ } else if (expectedContent.isEmpty()){
+ char buffer[512];
+ snprintf(buffer, sizeof buffer, "%s has no content. Does it exist?",
+ current);
+ error(buffer);
+ } else {
+ QList<QByteArray> expLines = expectedContent.split('\n');
+ QList<QByteArray> curLines = expectedContent.split('\n');
+ rc = assertEquals(expLines, curLines, file, lineNo);
+ }
+ return rc;
+}
+
/**
* @brief Writes an info.
*
QByteArray RplTest::getTempFile(const char* node, const char* parent,
bool deleteIfExists) {
QByteArray dir = getTempDir(parent);
- QByteArray rc = dir + m_separator + node;
+ QByteArray rc = dir;
+ if (! rc.endsWith(m_separator))
+ rc += m_separator;
+ rc += node;
struct stat info;
if(deleteIfExists && stat(rc.constData(), &info) == 0)
unlink(rc.constData());
bool assertFalse(bool condition, const char* file, int lineNo);
bool assertNull(const void* ptr, const char* file, int lineNo);
bool assertNotNull(const void* ptr, const char* file, int lineNo);
+ bool assertEqualFiles(const char* expected, const char* current,
+ const char* file, int lineNo);
bool log(const char* message);
bool error(const char* message, ...);
QByteArray getTempDir(const char* node, const char* parent = NULL,
#define checkF(current) assertFalse(current, __FILE__, __LINE__)
#define checkN(current) assertNull(current, __FILE__, __LINE__)
#define checkNN(current) assertNotNull(current, __FILE__, __LINE__)
-
+#define checkFiles(expected, current) assertEqualFiles(expected, current, __FILE__, __LINE__)
#endif // RPLTEST_HPP
if (type == SST_GLOBAL){
m_classes[RplASInteger::m_instance.name()] = &RplASInteger::m_instance;
m_classes[RplASBoolean::m_instance.name()] = &RplASBoolean::m_instance;
- m_classes[RplASFloat::m_instance.name()] = &RplASBoolean::m_instance;
+ m_classes[RplASFloat::m_instance.name()] = &RplASFloat::m_instance;
m_classes[RplASString::m_instance.name()] = &RplASString::m_instance;
m_classes[RplASList::m_instance.name()] = &RplASList::m_instance;
m_classes[RplASMap::m_instance.name()] = &RplASMap::m_instance;
}
-
}
/**
* @return NULL: not found<br>
* otherwise: the class
*/
-RplASClass*RplSymbolSpace::findClass(const QString& name) const
+RplASClass* RplSymbolSpace::findClass(const QString& name) const
{
- return NULL;
+ RplASClass* rc = NULL;
+ if (m_classes.contains(name))
+ rc = m_classes[name];
+ else if (m_parent != NULL)
+ rc = m_parent->findClass(name);
+ return rc;
}
/**
clazz->dump(fp, indent + 1);
}
- fprintf(fp, "== Variables:\n");
+ fprintf(fp, "%s== Variables:\n", tabs);
sorted.clear();
sorted.reserve(m_variables.size());
VariableMap::iterator it3;
RplVariable* var = m_variables[*it4];
var->dump(fp, indent + 1);
}
- fprintf(fp, "== Body:\n");
- m_body->dump(fp, indent + 1);
+ fprintf(fp, "%s== Body:%s\n", tabs, m_body == NULL ? " <none>" : "");
+ if (m_body != NULL)
+ m_body->dump(fp, indent + 1);
}
/**
}
return rc;
}
+/**
+ * @brief Returns the body (a abstract syntax tree) of the symbol space.
+ *
+ * @return NULL: no body available<br>
+ * othewise: the body of the instance
+ */
+RplASItem* RplSymbolSpace::body() const
+{
+ return m_body;
+}
+
+/**
+ * @brief Sets the body (a abstract syntax tree) of the symbol space.
+ *
+ * @param body the new body
+ */
+void RplSymbolSpace::setBody(RplASItem* body)
+{
+ m_body = body;
+}
+
/**
* @brief Returns the name of the symbol space.
*
* @brief Constructor.
*/
RplASBoolean::RplASBoolean() :
- RplASClass("Boolean")
+ RplASClass("Bool")
{
}
/**
* @brief Constructor.
*/
RplASFloat::RplASFloat() :
- RplASClass("Boolean")
+ RplASClass("Float")
{
}
* @brief Constructor.
*/
RplASInteger::RplASInteger() :
- RplASFloat("Integer")
+ RplASFloat("Int")
{
}
* @brief Constructor.
*/
RplASString::RplASString() :
- RplASClass("String")
+ RplASClass("Str")
{
}
/**
RplVariable* findVariable(const QString& name) const;
RplASClass* findClass(const QString& name) const;
void dump(FILE* fp, int indent, const char* header = NULL);
+ QString name() const;
+ RplASItem* body() const;
+ void setBody(RplASItem* body);
public:
static void initGlobal(RplSymbolSpace& global);
static const char* spaceTypeName(SymbolSpaceType type);
RplASItem* m_body;
public:
static RplSymbolSpace m_global;
- QString name() const;
};
class RplASBoolean : public RplASClass {
rc.sprintf("%d", m_value.m_int);
break;
case DT_OBJECT:
- m_class->toString(m_value.m_object, maxLength);
+ rc = m_class->toString(m_value.m_object, maxLength);
break;
default:
case DT_UNDEF:
*/
RplASItem::RplASItem(RplASItemType type) :
m_id(m_nextId++),
- m_type(type),
+ m_nodeType(type),
m_flags(0),
m_position(NULL)
{
void RplASConstant::dump(FILE* fp, int indent)
{
DEFINE_TABS(indent);
- fprintf(fp, "%sConstant %d value: %s\n", tabs, m_id,
+ fprintf(fp, "%sconst id: %d value: %s\n", tabs, m_id,
m_value.toString().toUtf8().constData());
}
/** @class RplASNamedValue rplastree.hpp "rplexpr/rplastree.hpp"
*
- * @brief Implements the abstract base class of all named values, e.g. variables.
+ * @brief Implements a named values, a constant or a variable
*
*/
/**
* @brief Constructor.
*
- * @param type the type of the variable
* @param name the name of the instance
- * @param attr a bitmask of <code>Attribute</code> values, e.g. A_CONST
*/
-RplASNamedValue::RplASNamedValue(RplASClass* type,
- const QString& name, int attributes) :
+RplASNamedValue::RplASNamedValue(const QString& name) :
RplASNode1(AST_NAMED_VALUE),
m_name(name),
+ m_attributes(0),
+ m_dataType(NULL)
+{
+}
+
+/**
+ * @brief Constructor.
+ *
+ * @param itemType the node type, e.g. AST_VAR_DEFINITION
+ * @param dataType the data type (class)
+ * @param name the name of the variable
+ * @param attributes the attributes of the variable
+ */
+RplASNamedValue::RplASNamedValue(RplASItemType itemType, RplASClass* dataType,
+ const QString& name, int attributes) :
+ RplASNode1(itemType),
+ m_name(name),
m_attributes(attributes),
- m_type(type)
+ m_dataType(dataType)
{
}
+
/**
* @brief Returns the name.
*
void RplASNamedValue::dump(FILE* fp, int indent)
{
DEFINE_TABS(indent);
- fprintf(fp, "%sNamedValue %d attr: 0x%x\n", tabs, m_id, m_attributes);
+ fprintf(fp, "%snamedValue id: %d attr: 0x%x\n", tabs,
+ m_id, m_attributes);
+}
+
+/** @class RplVarDefinition rplastree.hpp "rplexpr/rplastree.hpp"
+ *
+ * @brief Implements variable definition for the Abstract Syntax Tree.
+ */
+
+/**
+ * @brief Constructor.
+ *
+ * @param type the data type
+ * @param name the name of the variable
+ * @param attributes the attributes of the variable
+ */
+RplASVarDefinition::RplASVarDefinition(RplASClass* type, const QString& name,
+ int attributes) :
+ RplASNamedValue(AST_VAR_DEFINITION, type, name, attributes),
+ RplASStatement()
+{
+}
+
+/**
+ * @brief Writes the internals into a file.
+ *
+ * @param fp target file
+ * @param indent nesting level
+ */
+void RplASVarDefinition::dump(FILE* fp, int indent)
+{
+ DEFINE_TABS(indent);
+ QByteArray name = m_name.toUtf8();
+ QByteArray className = m_dataType == NULL ? "?" : m_dataType->name().toUtf8();
+ fprintf(fp, "%svarDef %s (%s) id: %d succ: %d attr: 0x%x\n",
+ tabs, name.constData(), className.constData(),
+ m_id, m_successor == NULL ? 0 : m_successor->id(), m_attributes);
+ if (m_child != NULL)
+ m_child->dump(fp, indent + 1);
+ if (m_successor != NULL)
+ m_successor->dump(fp, indent);
+}
+
+void RplASVarDefinition::execute()
+{
+ //@ToDo
+}
+
+/**
+ * @brief Calculates the initialation value while interpreting.
+ *
+ * @param value OUT: ignored
+ */
+void RplASVarDefinition::calc(RplASVariant&)
+{
}
/** @class RplASNode1 rplastree.hpp "rplexpr/rplastree.hpp"
void RplASClass::dump(FILE* fp, int indent)
{
DEFINE_TABS(indent);
- fprintf(fp, "%sClass %s super: %s\n", tabs, m_name.toUtf8().constData(),
+ fprintf(fp, "%sclass %s super: %s\n", tabs, m_name.toUtf8().constData(),
m_superClass == NULL
? "<none>" : m_superClass->name().toUtf8().constData());
QList<QString> sorted;
{
bool rc = m_modules.contains(name);
if (! rc){
- // m_modules[0] is the "global" symbol space.
// freed in ~RplASTree()
RplSymbolSpace* space = new RplSymbolSpace(RplSymbolSpace::SST_MODULE,
- name, m_symbolSpaces[0]);
+ name, m_global);
m_symbolSpaceHeap[name] = space;
m_modules[name] = space;
m_symbolSpaces.append(space);
}
return rc;
}
+/**
+ * @brief Search for the symbol space of a given module.
+ *
+ * @param name the module's name
+ * @return NULL: not found<br>
+ * otherwise: the symbol space of the module
+ */
+RplSymbolSpace* RplASTree::findmodule(const QString& name)
+{
+ RplSymbolSpace* rc = m_modules.contains(name) ? m_modules[name] : NULL;
+ return rc;
+}
/**
* @brief Handles the end of a module.
void RplASBinaryOp::dump(FILE* fp, int indent)
{
DEFINE_TABS(indent);
- fprintf(fp, "%sBinOp %d op: %d left: %d right: %d\n", tabs, m_id, m_operator,
+ const QByteArray& opName = RplLexer::m_active->nameOfOp(m_operator);
+ fprintf(fp, "%sBinOp %d op: %s (%d) left: %d right: %d\n", tabs, m_id,
+ opName.constData(), m_operator,
m_child == NULL ? 0 : m_child->id(),
m_child2 == NULL ? 0 : m_child2->id());
if (m_child != NULL)
m_child->dump(fp, indent + 1);
if (m_child2 != NULL)
- m_child->dump(fp, indent + 1);
+ m_child2->dump(fp, indent + 1);
}
/** @class RplASMethod rplastree.hpp "rplexpr/rplastree.hpp"
RplASMethod::RplASMethod(const QString& name, RplASClass* type) :
RplASNode2(AST_METHOD),
m_name(name),
- m_type(type)
+ m_nodeType(type)
{
}
{
DEFINE_TABS(indent);
fprintf(fp, "%sMethod %d %s %s(", tabs, m_id,
- m_type == NULL ? "<NoneType>" : m_type->name().toUtf8().constData(),
+ m_nodeType == NULL ? "<NoneType>" : m_nodeType->name().toUtf8().constData(),
m_name.toUtf8().constData());
fprintf(fp, ") body: %d args: %d\n", m_child == NULL ? 0 : m_child->id(),
m_child2 == NULL ? 0 : m_child2->id());
RplASStatement()
{
}
+
AST_UNDEF,
AST_CONSTANT,
AST_NAMED_VALUE,
+ AST_VAR_DEFINITION,
AST_METHOD,
AST_ARGUMENT,
AST_INTRINSIC_METHOD,
virtual void dump(FILE* fp, int indent) = 0;
protected:
unsigned int m_id:16;
- RplASItemType m_type:8;
+ RplASItemType m_nodeType:8;
int m_flags:5;
int m_dataType: 3;
const RplSourcePosition* m_position;
};
public:
- RplASNamedValue(RplASClass* type, const QString& name,
- int attributes = A_NONE);
+ RplASNamedValue(const QString& name);
+ RplASNamedValue(RplASItemType itemType, RplASClass* dataType,
+ const QString& name, int attributes);
public:
QString name() const;
public:
virtual void calc(RplASVariant& value);
void dump(FILE* fp, int indent);
-private:
+protected:
QString m_name;
int m_attributes;
- RplASClass* m_type;
+ RplASClass* m_dataType;
+};
+
+class RplASStatement
+{
+public:
+ RplASStatement();
+ virtual ~RplASStatement();
+public:
+ virtual void execute() = 0;
+ RplASItem* successor() const;
+ void setSuccessor(RplASItem* successor);
+protected:
+ RplASItem* m_successor;
+};
+
+
+class RplASVarDefinition : public RplASNamedValue, public RplASStatement
+{
+public:
+ RplASVarDefinition(RplASClass* type, const QString& name,
+ int attributes = A_NONE);
+public:
+ virtual void execute();
+ virtual void calc(RplASVariant& value);
+ void dump(FILE* fp, int indent);
};
class RplASUnaryOp : public RplASNode1
int m_operator;
};
-class RplASStatement
-{
-public:
- RplASStatement();
- virtual ~RplASStatement();
-public:
- virtual void execute() = 0;
- RplASItem* successor() const;
- void setSuccessor(RplASItem* successor);
-
-private:
- RplASItem* m_successor;
-};
-
class RplASCondition : public RplASNode1, public RplASCalculable
{
public:
void dump(FILE* fp, int indent);
private:
QString m_name;
- RplASClass* m_type;
+ RplASClass* m_nodeType;
// body is m_child
// param1 is m_child2
};
RplASClass* findClass(const QString& name);
void clear();
void dump(const char* filename, int flags = DMP_ALL);
+ RplSymbolSpace*findmodule(const QString& name);
protected:
void init();
void destroy();
#define CHAR_INFO_SIZE (int(sizeof m_charInfo / sizeof m_charInfo[0]))
+RplLexer* RplLexer::m_active = NULL;
+
/** @class RplToken rpllexer.hpp "rplexpr/rpllexer.hpp"
*
* @brief Implements specific exception for the lexer.
charClassToCharInfo(restCharsId, CC_REST_ID, m_charInfo);
initializeComments(comments);
m_input.reserve(m_maxTokenLength*2);
+ if (m_active == NULL)
+ m_active = this;
}
/**
* @brief Destructor.
*/
RplLexer::~RplLexer()
{
+ if (m_active == this)
+ m_active = NULL;
}
/**
return rc;
}
+/**
+ * @brief Returns the name of an operator.
+ *
+ * @param op the operator id
+ * @return the name of the operator
+ */
+const QByteArray&RplLexer::nameOfOp(int op) const
+{
+ const QByteArray& rc = m_opNames.at(op);
+ return rc;
+}
+
/**
* @brief Returns whether an operator is right associative
* @param op op to test
char m_prioOfOp[128];
char m_assocOfOp[128];
QList<QByteArray> m_opNames;
+public:
+ static RplLexer* m_active;
};
L_PARSE_OPERAND_RPARENTH_FUNC,
L_TERM_WRONG_STRING,
L_TERM_WRONG_NUMBER,
- L_PARSE_OPERAND_WRONG = 2005,
+ L_PARSE_OPERAND_WRONG = 2005,
L_DEFINITION_NO_ID,
L_DEFINITION_WRONG_ID,
L_DEFINITION_UNKNOWN_CLASS,
L_DEFINITION_MISSING_ID,
- L_DEFINITION_NO_OP
+ L_DEFINITION_NO_OP = 2010,
+ L_DEFINITION_NO_SEMICOLON
};
* @param clazz NULL or the type of the variable
* @param attribute 0 or attribute of the variable: K_CONST or K_LAZY
*/
-RplASItem* RplMFParser::parseDefinition(Keyword attribute)
+RplASItem* RplMFParser::parseVarDefinition(Keyword attribute)
{
RplASNamedValue::Attributes attr = RplASNamedValue::A_NONE;
- RplToken* token;
+ RplToken* token = m_lexer.currentToken();
while(attribute == K_CONST || attribute == K_LAZY){
switch(attribute){
case K_CONST:
attribute = token->isTokenType(TOKEN_KEYWORD)
? (Keyword) token->id() : K_UNDEF;
}
- if (token->isTokenType(TOKEN_ID))
+ if (! token->isTokenType(TOKEN_ID))
syntaxError(L_DEFINITION_NO_ID, "class name expected, but no id found");
if (! token->isCapitalizedId())
syntaxError(L_DEFINITION_WRONG_ID,
token = m_lexer.nextNonSpaceToken();
if (! token->isTokenType(TOKEN_ID))
syntaxError(L_DEFINITION_MISSING_ID, "variable name expected");
- RplASNamedValue* rc = new RplASNamedValue(clazz, token->toString(), attr);
+ RplASNamedValue* rc = new RplASVarDefinition(clazz, token->toString(), attr);
+ rc->setPosition(m_lexer.currentPosition());
token = m_lexer.nextNonSpaceToken();
if (! token->isOperator(O_ASSIGN, O_SEMICOLON))
syntaxError(L_DEFINITION_NO_OP, "'=' or ';' expected");
rc->setChild(value);
token = m_lexer.currentToken();
}
- if (token->isOperator(O_SEMICOLON)){
- syntaxError(L_DEFINITION_NO_OP, "';' expected");
+ if (! token->isOperator(O_SEMICOLON)){
+ syntaxError(L_DEFINITION_NO_SEMICOLON, "';' expected");
}
return rc;
}
case TOKEN_REAL:
{
RplASConstant* constant = new RplASConstant();
+ constant->setPosition(m_lexer.currentPosition());
rc = constant;
switch(token->tokenType()){
case TOKEN_STRING:
switch(tokenType){
case TOKEN_OPERATOR:
{
- if (IS_BINARY_OP(tokenType)){
+ Operator opId = (Operator) token->id();
+ if (IS_BINARY_OP(opId)){
RplASBinaryOp* op = new RplASBinaryOp();
- int opId = token->id();
- op->setOperator(opId);
op->setPosition(m_lexer.currentPosition());
+ op->setOperator(opId);
int prio = m_lexer.prioOfOp(token->id());
if (prio < lastPrio
op->setChild(top2->child2());
top2->setChild2(op);
}
+ lastPrio = prio;
op->setChild2(parseOperand(depth));
} else
again = false;
RplASStatement* lastStatement = NULL;
bool again = true;
while(again) {
- switch(token->tokenType())
- {
- case TOKEN_STRING:
- case TOKEN_NUMBER:
- case TOKEN_REAL:
- case TOKEN_OPERATOR:
- m_lexer.undoLastToken();
- item = parseExpr();
- break;
- case TOKEN_KEYWORD:
- switch (token->id()){
- case K_IF:
- item = parseIf();
- break;
- case K_WHILE:
- item = parseWhile();
- break;
- case K_REPEAT:
- item = parseRepeat();
- break;
- case K_FOR:
- item = parseFor();
- break;
- case K_CLASS:
- item = parseClass();
- break;
- case K_FUNCTION:
- case K_GENERATOR:
- item = parseMethodDefinition();
+ token = m_lexer.currentToken();
+ try {
+ switch(token->tokenType())
+ {
+ case TOKEN_STRING:
+ case TOKEN_NUMBER:
+ case TOKEN_REAL:
+ case TOKEN_OPERATOR:
+ m_lexer.undoLastToken();
+ item = parseExpr();
break;
- case K_IMPORT:
- parseImport();
+ case TOKEN_KEYWORD:
+ switch (token->id()){
+ case K_IF:
+ item = parseIf();
+ break;
+ case K_WHILE:
+ item = parseWhile();
+ break;
+ case K_REPEAT:
+ item = parseRepeat();
+ break;
+ case K_FOR:
+ item = parseFor();
+ break;
+ case K_CLASS:
+ item = parseClass();
+ break;
+ case K_FUNCTION:
+ case K_GENERATOR:
+ item = parseMethodDefinition();
+ break;
+ case K_IMPORT:
+ parseImport();
+ break;
+ case K_CONST:
+ case K_LAZY:
+ item = parseVarDefinition((Keyword) token->id());
+ break;
+ default:
+ break;
+ }
break;
- case K_CONST:
- case K_LAZY:
- item = parseDefinition(NULL, (Keyword) token->id());
+ case TOKEN_ID:
+ {
+ if (token->isCapitalizedId()){
+ item = parseVarDefinition(K_UNDEF);
+ } else {
+ m_lexer.undoLastToken();
+ item = parseExpr();
+ }
break;
- case K_BOOL:
- parseDefinition(&RplASBoolean::m_instance, K_UNDEF);
+ }
+ case TOKEN_END_OF_SOURCE:
+ again = false;
break;
default:
break;
}
- break;
- case TOKEN_ID:
- {
- if (token->isCapitalizedId()){
- item = parseDefinition(K_UNDEF);
- } else {
- m_lexer.undoLastToken();
- item = parseExpr();
+ if (! token->isTokenType(TOKEN_END_OF_SOURCE)){
+ if (body == NULL){
+ body = item;
+ } else {
+ lastStatement->setSuccessor(item);
+ }
+ lastStatement = dynamic_cast<RplASStatement*>(item);
+ if (lastStatement == NULL)
+ assert("wrong item type" == NULL);
+ token = m_lexer.nextNonSpaceToken();
}
- break;
- }
- case TOKEN_END_OF_SOURCE:
- again = false;
- break;
- default:
- break;
- }
- if (body == NULL){
- body = item;
- } else {
- lastStatement->setSuccessor(item);
+ } catch(RplSyntaxError exc){
+ // we look for the end of the statement:
+ token = m_lexer.currentToken();
+ RplTokenType type;
+ Operator op;
+ Keyword key;
+ while( (type = token->tokenType()) != TOKEN_END_OF_SOURCE)
+ if (type == TOKEN_OPERATOR
+ && ((op = Operator(token->id())) == O_SEMICOLON
+ || op == O_SEMI_SEMICOLON))
+ break;
+ else if (type == TOKEN_KEYWORD){
+ key = Keyword(token->id());
+ if (key == K_ENDC || key == K_ENDF){
+ // we need the token again!
+ m_lexer.undoLastToken();
+ break;
+ } else if (key == K_FI || key == K_OD){
+ break;
+ } else {
+ token = m_lexer.nextNonSpaceToken();
+ }
+ } else {
+ token = m_lexer.nextNonSpaceToken();
+ }
}
- lastStatement = dynamic_cast<RplASStatement*>(item);
}
return body;
}
*/
void RplMFParser::parse()
{
-
+ RplSource* source = m_lexer.source();
+ RplSourceUnit* mainModule = source->currentReader()->currentSourceUnit();
+ QString mainModuleName = mainModule->name();
+ m_tree.startModule(mainModuleName);
+ try {
+ RplASItem* body = parseBody();
+ RplSymbolSpace* module = m_tree.findmodule(mainModuleName);
+ if (module != NULL)
+ module->setBody(body);
+ } catch(RplParserStop exc){
+ printf("compiling stopped: %s\n", exc.reason());
+ }
}
/**
RplASItem* parseWhile();
RplASItem* parseRepeat();
RplASItem* parseFor();
- RplASItem* parseDefinition(Keyword attribute);
+ RplASItem* parseVarDefinition(Keyword attribute);
RplASItem* parseExpr();
RplASItem* parseBody();
RplASItem* parseMethodDefinition();
RplASItem* parseOperand(int level);
RplASItem* parseTerm(int depth);
private:
+ ///syntax token builder.
+ /// Note: the super class contains a reference with the same name
RplLexer m_lexer;
};
m_reason(reason)
{
}
+/**
+ * @brief Returns the description of the exception.
+ *
+ * @return the reason
+ */
+const char* RplSyntaxError::reason() const
+{
+ return m_reason;
+}
/** @class RplParserStop rplparser.hpp "rplexpr/rplparser.hpp"
*
{
public:
RplSyntaxError(const char* reason);
+public:
+ const char* reason() const;
private:
const char* m_reason;
};
void addMessage(char prefix, int location, const char* format, va_list varList);
protected:
- RplLexer m_lexer;
+ RplLexer& m_lexer;
RplASTree& m_tree;
MessageList m_messages;
int m_errors;
--- /dev/null
+=== Globals:
+= global (global) parent: <none>
+== Classes:
+ class Boolean super: <none>
+ class Boolean super: <none>
+ class Integer super: Float
+ class List super: <none>
+ class Map super: <none>
+ class String super: <none>
+== Variables:
+== Body: <none>
+ = <test> (module) parent: global
+ == Classes:
+ == Variables:
+ == Body:
+ BinOp 2 op: + (26) left: 1 right: 3
+ Constant 1 value: 2
+ Constant 3 value: 3
--- /dev/null
+=== Globals:
+= global (global) parent: <none>
+== Classes:
+ class Bool super: <none>
+ class Float super: <none>
+ class Int super: Float
+ class List super: <none>
+ class Map super: <none>
+ class Str super: <none>
+== Variables:
+== Body: <none>
+ = <test> (module) parent: global
+ == Classes:
+ == Variables:
+ == Body:
+ varDef i (Int) id: 1 succ: 3 attr: 0x0
+ const id: 2 value: 3
+ varDef s (Str) id: 3 succ: 5 attr: 0x10
+ const id: 4 value: 'Hi'
+ varDef l (List) id: 5 succ: 0 attr: 0x2
}
void testExpr(){
+ extern void testRplMFParser();
+ testRplMFParser();
+
extern void testRplASTree();
testRplASTree();
extern void testRplSource();
#include "rplexpr/rplexpr.hpp"
#include "rplcore/rpltest.hpp"
-class TestRplMFParser : public RplTest, public RplMFParser{
+class TestRplMFParser : public RplTest{
private:
RplSource m_source;
RplASTree m_tree;
public:
TestRplMFParser() :
RplTest("RplMFParser"),
- RplMFParser(m_source, m_tree),
m_source(),
m_tree(),
m_reader(m_source)
m_tree.clear();
m_source.clear();
m_reader.replaceSource("<test>", content);
+ m_source.addReader(&m_reader);
+ m_source.addSourceUnit(m_reader.currentSourceUnit());
+ }
+
+private:
+ void checkAST(const char* fileExpected, int lineNo){
+ QByteArray fnExpected = "test";
+ fnExpected += QDir::separator().toLatin1();
+ fnExpected += "rplmfparser";
+ fnExpected += (char) QDir::separator().toLatin1();
+ fnExpected += fileExpected;
+ QByteArray fnCurrent = getTempFile(fileExpected, "rplmfparser");
+ m_tree.dump(fnCurrent);
+ assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
+ __FILE__, lineNo);
}
public:
setSource("2+3*4");
RplMFParser parser(m_source, m_tree);
parser.parse();
+ checkAST("baseTest.txt", __LINE__);
}
void defTest(){
- setSource("int i = 3; Str s = 'Hi; List l = [3, 'v4'];");
+ setSource("Int i = 3; const lazy Str s = 'Hi'; const List l;");
RplMFParser parser(m_source, m_tree);
parser.parse();
+ checkAST("defTest.txt", __LINE__);
}
virtual void doIt(void) {
- //baseTest();
- //defTest();
+ defTest();
+ baseTest();
}
};
void testRplMFParser() {