void RplSymbolSpace::finishScope(RplASScope& scope)
{
// in methods/classes not needed:
- for (ix = scope.m_varNoAtStart; ix < m_listOfVars.size(); ix++){
+ for (int ix = scope.m_varNoAtStart; ix < m_listOfVars.size(); ix++){
const QString& name = m_listOfVars[ix]->name();
if (m_variables.contains(name))
m_variables.remove(name);
}
}
+/**
+ * @brief Search a variable in the symbol space.
+ *
+ * @param name variable to find
+ *
+ * @return NULL: not found<br>
+ * otherwise: the variable
+ */
+RplASVarDefinition* RplSymbolSpace::findVariable(const QString& name) const
+{
+ RplASVarDefinition* rc = NULL;
+ if (m_variables.contains(name))
+ rc = m_variables[name];
+ else if (m_parent != NULL)
+ rc = m_parent->findVariable(name);
+ return rc;
+}
+
/**
* @brief Search the class in the symbol space hierarchy.
*
{
m_type = type;
}
-
+/**
+ * @brief Returns the name of the variable.
+ *
+ * @return the name
+ */
+const QString& RplVariable::name() const
+{
+ return m_name;
+}
/** @class RplVariable rplastree.hpp "rplexpr/rplastree.hpp"
*
RplASClass* type() const;
void setType(RplASClass* type);
+ const QString& name() const;
protected:
QString m_name;
class RplASScope
{
-public:
- RplASScope();
public:
int m_varNoAtStart;
};
public:
void startScope(RplASScope& scope);
void finishScope(RplASScope& scope);
- RplVariable* findVariable(const QString& name) const;
+ RplASVarDefinition* findVariable(const QString& name) const;
RplASClass* findClass(const QString& name) const;
RplASMethod* findMethod(const QString& name) const;
void dump(RplWriter& writer, int indent, const char* header = NULL);
const QString& name() const;
RplASItem* body() const;
void setBody(RplASItem* body);
- RplASItem* addVariable(RplASVarDefinition* variable);
+ RplASItem* addVariable(RplASVarDefinition* variable, int& varNo);
RplASItem* addMethod(RplASMethod* method);
RplASUserClass* addClass(RplASUserClass* clazz);
RplSymbolSpace* parent() const;
* @return true: the module is new<br>
* false: the module is yet known
*/
-bool RplASTree::startModule(const QString& name)
+bool RplASTree::startModule(RplSourceUnitName name)
{
bool rc = m_modules.contains(name);
if (! rc){
* @brief Handles the end of a module.
* @param name the module's name
*/
-void RplASTree::finishModule(const QString& name)
+void RplASTree::finishModule(RplSourceUnitName name)
{
RplSymbolSpace* top = m_symbolSpaces.at(m_symbolSpaces.size() - 1);
if (top->name() != name)
throw RplException("RplASTree::finishModule(): module is not top: %s",
- name.toUtf8().constData());
+ name);
else {
m_symbolSpaces.removeLast();
// "global" is always the bottom:
RplASTree();
~RplASTree();
public:
- bool startModule(const QString& name);
- void finishModule(const QString& name);
+ bool startModule(RplSourceUnitName name);
+ void finishModule(RplSourceUnitName name);
RplSymbolSpace* startClassOrMethod(const QString& name,
RplSymbolSpace::SymbolSpaceType type);
void finishClassOrMethod(const QString& name);
*
* @param unit the new source unit
*/
-void RplLexer::startUnit(const QString& unit)
+void RplLexer::startUnit(RplSourceUnitName unit)
{
m_source->startUnit(unit, *m_currentPosition);
}
RplToken* nextNonSpaceToken();
size_t maxTokenLength() const;
void setMaxTokenLength(size_t maxTokenLength);
- void startUnit(const QString& unit);
+ void startUnit(RplSourceUnitName unit);
RplSource* source();
int prioOfOp(int op) const;
const QByteArray& nameOfOp(int op) const;
RplASItem* rc = NULL;
if (parent == NULL){
RplSymbolSpace* space = m_tree.currentSpace();
- RplVariable* var = space->findVariable(name);
+ RplASVarDefinition* var = space->findVariable(var->name());
RplASClass* clazz = NULL;
if (var != NULL)
- clazz = var->type();
- RplASNamedValue* var = new RplASNamedValue(clazz, space,
+ clazz = var->datatype();
+ RplASNamedValue* var2 = new RplASNamedValue(clazz, space,
name, RplASNamedValue::A_NONE);
- var->setPosition(position);
- rc = var;
+ var2->setPosition(position);
+ rc = var2;
} else {
RplASField* field = new RplASField(name);
field->setPosition(position);
*
* @param name the name of the module (without path)
*/
-RplASItem* RplMFParser::parseModule(const QString& name)
+RplASItem* RplMFParser::parseModule(RplSourceUnitName name)
{
m_tree.startModule(name);
// parse until EOF:
{
RplSource* source = m_lexer.source();
RplSourceUnit* mainModule = source->currentReader()->currentSourceUnit();
- QString mainModuleName = mainModule->name();
+ RplSourceUnitName mainModuleName = mainModule->name();
try {
RplASItem* body = parseModule(mainModuleName);
RplSymbolSpace* module = m_tree.findmodule(mainModuleName);
if (module != NULL)
module->setBody(body);
} catch(RplParserStop exc){
- printf("compiling stopped: %s\n", exc.reason());
+ printf("compiling aborted: %s\n", exc.reason());
}
}
void parseMethod();
void parseClass();
void parseImport();
- RplASItem* parseModule(const QString& name);
+ RplASItem* parseModule(RplSourceUnitName name);
void parse();
RplASItem*parseExprStatement(bool eatSemicolon = true);
RplASItem*parseList();
char buffer[2048];
QString msg;
snprintf(buffer, sizeof buffer, "%c%04d %s:%d-%d: ", prefix, location,
- position->sourceUnit()->name().toUtf8().constData(),
+ position->sourceUnit()->name(),
position->lineNo(), position->column());
int used = strlen(buffer);
int length = strlen(message);
* @param name name of the unit
* @param reader the reader which can read the unit
*/
-RplSourceUnit::RplSourceUnit(const QString& name, RplReader* reader) :
+RplSourceUnit::RplSourceUnit(RplSourceUnitName name, RplReader* reader) :
m_name(name),
m_lineNo(0),
m_reader(reader) {
* @brief Returns the name.
* @return the name
*/
-const QString& RplSourceUnit::name() const {
- return m_name;
+RplSourceUnitName RplSourceUnit::name() const {
+ return m_name.constData();
}
/**
*/
QString RplSourcePosition::toString() const
{
- QString rc;
- if (m_sourceUnit != NULL)
- rc = m_sourceUnit->name();
- QTextStream stream(&rc);
- stream << ":" << m_lineNo << ":" << m_column << ": ";
- return rc;
+ char buffer[512];
+ utf8(buffer, sizeof buffer);
+
+ return QString(buffer);
}
/**
*/
char* RplSourcePosition::utf8(char buffer[], size_t bufferSize) const
{
- QByteArray module = m_sourceUnit->name().toUtf8();
- snprintf(buffer, bufferSize, "%s:%d:%d", module.constData(),
+ snprintf(buffer, bufferSize, "%s:%d:%d",
+ m_sourceUnit == NULL ? "" : m_sourceUnit->name(),
m_lineNo, m_column);
return buffer;
}
*/
void RplReader::clear()
{
- QMap<QString, RplSourceUnit*>::iterator it;
+ UnitMap::iterator it;
for(it = m_units.begin(); it != m_units.end(); it++) {
RplStringSourceUnit* unit = (RplStringSourceUnit*)(*it);
delete unit;
*
* @param sourceUnit the name of the new source unit
*/
-bool RplReader::setCurrentSourceUnit(const QString& sourceUnit) {
+bool RplReader::setCurrentSourceUnit(RplSourceUnitName sourceUnit) {
bool rc = m_units.contains(sourceUnit);
if(rc) {
m_currentSourceUnit = m_units.value(sourceUnit);
* @param unit unit to find
* @return a permanently valid unit name
*/
-const char* RplSource::permanentUnitName(const char* unit) {
+RplSourceUnitName RplSource::permanentUnitName(RplSourceUnitName unit) {
return unit;
}
* @param caller the position of the include
*
*/
-bool RplSource::startUnit(const QString& unit,
+bool RplSource::startUnit(RplSourceUnitName unit,
const RplSourcePosition& caller) {
m_sourcePositionStack.push_back(&caller);
RplReader* reader = NULL;
* @param content content of the unit
* @param reader the parent
*/
-RplStringSourceUnit::RplStringSourceUnit(const QString& name,
- const QString& content, RplStringReader* reader) :
+RplStringSourceUnit::RplStringSourceUnit(RplSourceUnitName name,
+ const RplSourceUnitContent& content, RplStringReader* reader) :
RplSourceUnit(name, reader),
m_currentPosition(0),
m_content(content) {
*
* @return the content
*/
-const QString& RplStringSourceUnit::content() const {
+const RplSourceUnitContent& RplStringSourceUnit::content() const {
return m_content;
}
* otherwise: an instance of a sub class of
* <code>RplSourceUnit</code>
*/
-RplSourceUnit* RplStringReader::openSourceUnit(const QString& unit) {
+RplSourceUnit* RplStringReader::openSourceUnit(RplSourceUnitName unit) {
RplSourceUnit* rc = NULL;
if(setCurrentSourceUnit(unit)) {
rc = m_currentSourceUnit;
* @return false: no more input available<br>
* true: success
*/
-bool RplStringReader::nextLine(int maxSize, QString& buffer,
+bool RplStringReader::nextLine(int maxSize, RplSourceUnitContent& buffer,
bool& hasMore) {
bool rc = m_currentSourceUnit != NULL;
if (rc){
* @return false: no more input available<br>
* true: success
*/
-bool RplStringReader::fillBuffer(int maxSize, QString& buffer,
+bool RplStringReader::fillBuffer(int maxSize, RplSourceUnitContent& buffer,
bool& hasMore) {
RplStringSourceUnit* unit = (RplStringSourceUnit*) m_currentSourceUnit;
int start = unit->currentPosition();
- const QString& content = unit->content();
+ const RplSourceUnitContent& content = unit->content();
int end = content.indexOf("\n", start);
hasMore = false;
if(end < 0) {
* @param name name of the medium
* @param content
*/
-void RplStringReader::addSource(const QString& name,
- const QString& content) {
+void RplStringReader::addSource(RplSourceUnitName name,
+ const RplSourceUnitContent& content) {
// Deletion in the destructor of the base class RplReader
RplStringSourceUnit* unit = new RplStringSourceUnit(name, content, this);
- m_units.insert(m_units.begin(), name, unit);
+ m_units.insert(m_units.begin(), unit->name(), unit);
m_currentSourceUnit = unit;
}
* @param name name of the source unit
* @param content new content
*/
-void RplStringReader::replaceSource(const QString& name, const QString& content)
+void RplStringReader::replaceSource(RplSourceUnitName name, const RplSourceUnitContent& content)
{
if (m_units.contains(name)){
RplStringSourceUnit* unit = dynamic_cast<RplStringSourceUnit*>(m_units[name]);
* This is the mostly used implementation of the RplSourceUnit/RplReader.
*/
-/**
- * @brief Constructor.
- *
- * @param file name of the directory
- * @param reader the parent
- */
-RplFileSourceUnit::RplFileSourceUnit(const QDir& file,
+
+RplFileSourceUnit::RplFileSourceUnit(RplSourceUnitName filename,
RplFileReader* reader) :
- RplSourceUnit(file.absolutePath(), reader),
+ RplSourceUnit(filename, reader),
m_currentPosition(0),
- m_file(file.absolutePath()),
- m_textStream(&m_file),
+ m_fp(fopen(filename, "r")),
+ m_textStream(m_fp, QIODevice::ReadOnly),
m_line()
{
}
+
/**
* @brief Destructor.
*/
-RplFileSourceUnit::~RplFileSourceUnit() {
+RplFileSourceUnit::~RplFileSourceUnit()
+{
+ fclose(m_fp);
+}
+
+bool RplFileSourceUnit::isOpen() const
+{
+ return m_fp != NULL;
}
/** @class RplFileReader rplsource.hpp "rplexpr/rplsource.hpp"
*
* @brief Constructor.
*/
RplFileReader::RplFileReader(RplSource& source) :
- RplReader(source) {
+ RplReader(source)
+{
}
/**
* otherwise: an instance of a sub class of
* <code>RplSourceUnit</code>
*/
-RplSourceUnit* RplFileReader::openSourceUnit(const QString& unit) {
+RplSourceUnit* RplFileReader::openSourceUnit(RplSourceUnitName unit) {
RplSourceUnit* rc = NULL;
if(m_units.contains(unit)) {
rc = *m_units.find(unit);
- m_currentUnit = (RplFileSourceUnit*) rc;
+ m_currentSourceUnit = static_cast<RplFileSourceUnit*>(rc);
}
return rc;
}
* @return false: no more input available<br>
* true: success
*/
-bool RplFileReader::nextLine(int maxSize, QString& buffer,
+bool RplFileReader::nextLine(int maxSize, RplSourceUnitContent& buffer,
bool& hasMore) {
- RplFileSourceUnit* unit = (RplFileSourceUnit*) m_currentUnit;
+ RplFileSourceUnit* unit = static_cast<RplFileSourceUnit*>
+ (m_currentSourceUnit);
bool rc = ! unit->m_textStream.atEnd();
- if(rc) {
+ if(! rc) {
+ m_source.popSourceUnit(this);
+ } else {
unit->m_line = unit->m_textStream.readLine();
rc = fillBuffer(maxSize, buffer, hasMore);
}
* @return false: no more input available<br>
* true: success
*/
-bool RplFileReader::fillBuffer(int maxSize, QString& buffer,
+bool RplFileReader::fillBuffer(int maxSize, RplSourceUnitContent& buffer,
bool& hasMore) {
- RplFileSourceUnit* unit = (RplFileSourceUnit*) m_currentUnit;
+ RplFileSourceUnit* unit = static_cast<RplFileSourceUnit*>(m_currentSourceUnit);
int start = unit->m_currentPosition;
- const QString& content = unit->m_line;
+ const RplSourceUnitContent& content = unit->m_line;
int size = content.size() - start;
if(size > maxSize)
size = maxSize;
*
* @param dirEntry the file
*/
-void RplFileReader::addSource(const QDir& dirEntry) {
- QString name = dirEntry.absolutePath();
+void RplFileReader::addSource(RplSourceUnitName filename) {
// Deleting in ~RplSourceUnit():
- RplFileSourceUnit* unit = new RplFileSourceUnit(dirEntry, this);
- m_units.insert(m_units.begin(), name, unit);
+ RplFileSourceUnit* unit = new RplFileSourceUnit(filename, this);
+ m_units.insert(m_units.begin(), unit->name(), unit);
+ m_currentSourceUnit = unit;
}
#ifndef RPLSOURCE_HPP
#define RPLSOURCE_HPP
+// type of buffer names and filenames. Codec: UTF-8
+typedef const char* RplSourceUnitName;
+
+typedef QString RplSourceUnitContent;
+
class RplSource;
class RplReader;
class RplSourceUnit {
public:
- RplSourceUnit(const QString& name, RplReader* reader);
+ RplSourceUnit(const char* name, RplReader* reader);
virtual ~RplSourceUnit();
public:
- const QString& name() const;
+ const char* name() const;
int lineNo() const;
void setLineNo(int lineNo);
RplReader* reader() const;
protected:
- QString m_name;
+ QByteArray m_name;
int m_lineNo;
RplReader* m_reader;
};
};
class RplReader {
+public:
+ typedef QMap<RplSourceUnitName, RplSourceUnit*> UnitMap;
public:
RplReader(RplSource& source);
~RplReader();
* for the source. This is normally a sub class of
* <code>RplSourceUnit</code>
*/
- virtual RplSourceUnit* openSourceUnit(const QString& unit) = 0;
+ virtual RplSourceUnit* openSourceUnit(const char* unit) = 0;
/**
* @brief Reads the first part of the next line into a given buffer.
*
* @return true: the read was successful<br>
* false: no more input is available
*/
- virtual bool nextLine(int maxSize, QString& buffer, bool& hasMore) = 0;
+ virtual bool nextLine(int maxSize, RplSourceUnitContent& buffer,
+ bool& hasMore) = 0;
/**
* @brief Reads the next part of the current line into a given buffer.
*
* @return true: the read was successful<br>
* false: no more input is available
*/
- virtual bool fillBuffer(int maxSize, QString& buffer, bool& hasMore) = 0;
+ virtual bool fillBuffer(int maxSize, RplSourceUnitContent& buffer,
+ bool& hasMore) = 0;
public:
virtual void clear();
RplSource& source();
RplSourceUnit* currentSourceUnit() const;
- bool setCurrentSourceUnit(const QString& currentSourceUnit);
+ bool setCurrentSourceUnit(RplSourceUnitName currentSourceUnit);
protected:
void removeSourceUnit();
protected:
RplSourceUnit* m_currentSourceUnit;
/// name -> source
- QMap<QString, RplSourceUnit*> m_units;
+ UnitMap m_units;
RplSource& m_source;
};
QStack<const RplSourcePosition*> sourcePositionStack() const;
QStack<RplSourceUnit*>& sourceUnitStack();
- bool startUnit(const QString& unit, const RplSourcePosition& caller);
+ bool startUnit(const char* unit, const RplSourcePosition& caller);
void pushSourceUnit(RplSourceUnit* unit);
RplSourceUnit* popSourceUnit(RplReader* reader);
RplReader* currentReader();
class RplStringSourceUnit : public RplSourceUnit {
friend class RplStringReader;
public:
- RplStringSourceUnit(const QString& name,
- const QString& content, RplStringReader* reader);
+ RplStringSourceUnit(RplSourceUnitName name,
+ const RplSourceUnitContent& content,
+ RplStringReader* reader);
virtual ~RplStringSourceUnit();
public:
int currentPosition() const;
void setCurrentPosition(int currentPosition);
- const QString& content() const;
+ const RplSourceUnitContent& content() const;
private:
int m_currentPosition;
- QString m_content;
+ RplSourceUnitContent m_content;
};
class RplStringReader : public RplReader{
virtual ~RplStringReader();
// RplReader interface
public:
- virtual RplSourceUnit* openSourceUnit(const QString& unit);
- virtual bool nextLine(int maxSize, QString& buffer, bool& hasMore);
- virtual bool fillBuffer(int maxSize, QString& buffer, bool& hasMore);
+ virtual RplSourceUnit* openSourceUnit(RplSourceUnitName unit);
+ virtual bool nextLine(int maxSize, RplSourceUnitContent& buffer,
+ bool& hasMore);
+ virtual bool fillBuffer(int maxSize, RplSourceUnitContent& buffer,
+ bool& hasMore);
public:
- void addSource(const QString& name, const QString& content);
- void replaceSource(const QString& name, const QString& content);
+ void addSource(RplSourceUnitName name, const RplSourceUnitContent& content);
+ void replaceSource(RplSourceUnitName name, const RplSourceUnitContent& content);
};
class RplFileReader;
class RplFileSourceUnit : public RplSourceUnit {
friend class RplFileReader;
public:
- RplFileSourceUnit(const QDir& dir, RplFileReader* reader);
+ RplFileSourceUnit(RplSourceUnitName filename, RplFileReader* reader);
virtual ~RplFileSourceUnit();
+public:
+ bool isOpen() const;
private:
int m_currentPosition;
- QFile m_file;
+ FILE* m_fp;
QTextStream m_textStream;
- QString m_line;
+ RplSourceUnitContent m_line;
};
class RplFileReader : public RplReader{
virtual ~RplFileReader();
// RplReader interface
public:
- virtual RplSourceUnit* openSourceUnit(const QString& unit);
- virtual bool nextLine(int maxSize, QString& buffer, bool& hasMore);
- virtual bool fillBuffer(int maxSize, QString& buffer, bool& hasMore);
+ virtual RplSourceUnit* openSourceUnit(RplSourceUnitName unit);
+ virtual bool nextLine(int maxSize, RplSourceUnitContent& buffer,
+ bool& hasMore);
+ virtual bool fillBuffer(int maxSize, RplSourceUnitContent& buffer,
+ bool& hasMore);
public:
- void addSource(const QDir& dirEntry);
-private:
- /// name -> source
- QMap<QString, RplFileSourceUnit*> m_units;
- RplFileSourceUnit* m_currentUnit;
+ void addSource(RplSourceUnitName filename);
};
}
void testExpr(){
+ extern void testRplBenchmark();
+ testRplBenchmark();
+
extern void testRplVM();
- testRplVM();
+ //testRplVM();
extern void testRplMFParser();
testRplMFParser();
RplSource m_source;
RplStringReader m_reader;
RplStringSourceUnit m_unit;
+ RplASTree m_tree;
public:
TestRplASTree() :
RplTest("RplASTree"),
m_source(),
m_reader(m_source),
- m_unit("<main>", "", &m_reader)
+ m_unit("<main>", "", &m_reader),
+ m_tree()
{}
public:
void testRplASException() {
//checkE("Jonny", *value.asString());
}
void testRplASNamedValue(){
- RplASNamedValue value("gugo");
+ RplASNamedValue value(NULL, m_tree.symbolSpaces()[0], "gugo",
+ RplASNamedValue::A_GLOBAL);
checkE("gugo", value.name());
}
void testRplASCondition(){
--- /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.
+*/
+
+/** @file
+ * @brief Unit test of the abstract syntax tree.
+ */
+
+
+#include "rplcore/rplcore.hpp"
+#include "rplexpr/rplexpr.hpp"
+#include "rplcore/rpltest.hpp"
+
+class TestRplBenchmark : public RplTest{
+private:
+ const char* m_filename;
+ RplSource m_source;
+ RplFileReader m_reader;
+ RplASTree m_tree;
+public:
+ TestRplBenchmark() :
+ RplTest("RplBenchmark"),
+ m_filename("/home/ws/qt/rplqt/bench/mfbench.mf"),
+ m_source(),
+ m_reader(m_source),
+ m_tree()
+ {
+ m_source.addReader(&m_reader);
+ m_reader.addSource(m_filename);
+ }
+public:
+ void benchmark() {
+ time_t start = time(NULL);
+ RplMFParser parser(m_source, m_tree);
+ parser.parse();
+ time_t end = time(NULL);
+ printf("compilation: %d sec\n", int(end - start));
+ }
+ virtual void doIt() {
+ try{
+ RplFileSourceUnit* unit = dynamic_cast<RplFileSourceUnit*>
+ (m_reader.currentSourceUnit());
+ if (unit != NULL && ! unit->isOpen())
+ throw RplException("file not found: %s", m_filename);
+ benchmark();
+ } catch(RplException ex){
+ printf("%s\n", ex.getMessage().constData());
+ }
+ }
+};
+void testRplBenchmark() {
+ TestRplBenchmark test;
+ test.run();
+}
+
+
+
void testRplStringSourceUnit(){
RplStringReader reader(m_source);
QString content("a=1;\nveeeeeeeeery looooooooooooooong\n");
- RplStringSourceUnit unit(QString("test"), content, &reader);
+ RplStringSourceUnit unit("test", content, &reader);
unit.setLineNo(144);
checkE(144, unit.lineNo());
checkE("test", unit.name());
rplmfparser_test.cpp \
rplvm_test.cpp \
rplbytestorage_test.cpp \
- rplwriter_test.cpp
+ rplwriter_test.cpp \
+ rplbench.cpp