*/
void* RplASList::newValueInstance(void* source) const
{
- ListOfVariants* rc = new ListOfVariants();
+ RplASListOfVariants* rc = new RplASListOfVariants();
if (source != NULL){
- ListOfVariants* source2 = (ListOfVariants*) source;
+ RplASListOfVariants* source2 = (RplASListOfVariants*) source;
rc->reserve(source2->size());
- ListOfVariants::iterator it;
+ RplASListOfVariants::iterator it;
for (it = source2->begin();
it != source2->end();
it++){
*/
void RplASList::destroyValueInstance(void* object) const
{
- delete static_cast<ListOfVariants*>(object);
+ delete static_cast<RplASListOfVariants*>(object);
}
/**
{
bool rc = false;
if (object != NULL){
- ListOfVariants* list = static_cast<ListOfVariants*>(object);
+ RplASListOfVariants* list = static_cast<RplASListOfVariants*>(object);
if (list == NULL)
throw RplException("RplASList.boolValueOf(): not a list");
rc = ! list->empty();
QString rc;
rc.reserve(maxLength);
rc += "[";
- ListOfVariants* list = reinterpret_cast<ListOfVariants*>(object);
- ListOfVariants::iterator it;
+ RplASListOfVariants* list = reinterpret_cast<RplASListOfVariants*>(object);
+ RplASListOfVariants::iterator it;
bool first = true;
for(it = list->begin(); it != list->end(); it++){
if (first)
*/
void* RplASMap::newValueInstance(void* source) const
{
- MapValueType* rc = new MapValueType();
+ RplASMapValueType* rc = new RplASMapValueType();
if (source != NULL){
- MapValueType* source2 =
- static_cast<MapValueType*>(source);
+ RplASMapValueType* source2 =
+ static_cast<RplASMapValueType*>(source);
// rc->reserve(source2->size());
- MapValueType::iterator it;
+ RplASMapValueType::iterator it;
for (it = source2->begin(); it != source2->end(); it++){
// deleting in destroyValue():
const QString& key = it.key();
*/
void RplASMap::destroyValueInstance(void* object) const
{
- delete (MapValueType*) object;
+ delete (RplASMapValueType*) object;
}
/**
{
bool rc = false;
if (object != NULL){
- MapValueType* map = reinterpret_cast<MapValueType*>(object);
+ RplASMapValueType* map = reinterpret_cast<RplASMapValueType*>(object);
if (map == NULL)
throw RplException("RplASMap.boolValueOf(): not a map");
rc = map->empty() > 0;
QString rc;
rc.reserve(maxLength);
rc += "[";
- MapValueType* map = reinterpret_cast<MapValueType*>(object);
- MapValueType::iterator it;
+ RplASMapValueType* map = reinterpret_cast<RplASMapValueType*>(object);
+ RplASMapValueType::iterator it;
bool first = true;
for(it = map->begin(); it != map->end(); it++){
if (first)
*
* In this case we do nothing.
*
- * @param source ignored
+ * @param formula ignored
* @return
*/
-void*RplASFormula::newValueInstance(void*) const
+void*RplASFormula::newValueInstance(void* expr) const
{
- return NULL;
+ RplASExprStatement* rc = new RplASFormula();
+ rc->setChild();
}
/**
};
class RplASList : public RplASClass {
-public:
- typedef QList<RplASVariant*> ListOfVariants;
public:
RplASList();
public:
};
class RplASMap : public RplASClass {
-public:
- typedef QMap<QString, RplASVariant*> MapValueType;
public:
RplASMap();
public:
*
* @return the variant type
*/
-RplASClass* RplASVariant::getClass() const
+const RplASClass* RplASVariant::getClass() const
{
return m_class;
}
RplASNode1(AST_LIST_CONSTANT),
RplASCalculable()
{
+ m_value.setObject(RplASList::m_instance.newValueInstance(),
+ &RplASList::m_instance);
+}
+/**
+ * @brief Returns the list.
+ *
+ * @return the list
+ */
+RplASListOfVariants* RplASListConstant::list(){
+ RplASListOfVariants* rc = static_cast<RplASListOfVariants*>
+ (m_value.asObject(NULL));
+ return rc;
}
/**
fprintf(fp, "%slistConst id: %d %s\n", tabs, m_id,
positionStr(buffer, sizeof buffer));
- RplASList::ListOfVariants* list = (RplASList::ListOfVariants*)
- m_value.asObject();
QString sValue = m_value.toString(8092);
fprintf(fp, "%s\t%s\n", tabs, sValue.toUtf8().constData());
}
void setString(const QString& string);
QString toString(int maxLength = 80) const;
VariantType variantType() const;
- RplASClass* getClass() const;
+ const RplASClass* getClass() const;
protected:
void copyValue(const RplASVariant& source);
void destroyValue();
protected:
RplASItem* m_child5;
};
+typedef QList<RplASVariant*> RplASListOfVariants;
+typedef QMap<QString, RplASVariant*> RplASMapValueType;
class RplASListConstant : public RplASNode1, public RplASCalculable
{
public:
virtual void dump(FILE* fp, int indent);
RplASVariant& value();
+ RplASListOfVariants* list();
private:
RplASVariant m_value;
};
m_idRest2(),
m_currentToken(&m_token1),
m_waitingToken(NULL),
+ m_waitingToken2(NULL),
m_token1(TOKEN_UNDEF),
m_token2(TOKEN_UNDEF),
m_currentPosition(NULL),
+ m_waitingPosition1(NULL),
+ m_waitingPosition2(NULL),
m_maxTokenLength(64),
m_input(),
m_currentCol(0),
int ix;
if (m_waitingToken != NULL){
rc = m_currentToken = m_waitingToken;
- m_waitingToken = NULL;
+ m_waitingToken = m_waitingToken2;
+ m_waitingToken2 = NULL;
+ m_currentPosition = m_waitingPosition1;
+ m_waitingPosition1 = m_waitingPosition2;
+ m_waitingPosition2 = NULL;
} else {
m_currentToken->clear();
RplReader* reader = m_source->currentReader();
if (reader == NULL)
m_currentToken->m_tokenType = TOKEN_END_OF_SOURCE;
else {
- if (waitingPosition == NULL)
+ if (waitingPosition == NULL){
+ m_waitingPosition2 = m_currentPosition;
m_currentPosition = m_source->newPosition(m_currentCol);
- else {
- m_currentPosition = waitingPosition;
+ } else {
+ m_currentPosition = m_waitingPosition1;
+ m_waitingPosition1 = m_waitingPosition2;
+ m_waitingPosition2 = NULL;
((RplSourcePosition*)waitingPosition)->setSourceUnit(
m_source->currentReader()->currentSourceUnit());
((RplSourcePosition*)waitingPosition)->setColumn(m_currentCol);
return rc;
}
/**
- * @brief Makes that nextToken() returns the current token again.
+ * @brief Reverses the last <code>nextToken()</code>.
+ *
+ * Makes that <code>nextToken()</code> returns the current token again.
*/
void RplLexer::undoLastToken()
{
m_waitingToken = m_currentToken;
m_currentToken = m_currentToken == &m_token1 ? &m_token2 : &m_token1;
+ m_waitingPosition1 = m_currentPosition;
+}
+
+/**
+ * @brief Reverses the last <code>nextToken()</code>.
+ *
+ * Makes that <code>nextToken()</code> returns the current token again.
+ */
+void RplLexer::undoLastToken2()
+{
+ m_waitingToken = m_currentToken;
+ m_waitingToken2 = m_currentToken == &m_token1 ? &m_token2 : &m_token1;
+ m_waitingPosition2 = m_waitingPosition1;
+ m_waitingPosition1 = m_currentPosition;
+}
+
+/**
+ * @brief Prevents the current token from data loss.
+ *
+ * Usage:
+ * <pre><code>
+ * token1 = nextToken();
+ * saveLastToken();
+ * token2 = nextToken();
+ * </code></pre>
+ * Then <code>token1</code> and <code>token2</code> contains the wanted content.
+ */
+void RplLexer::saveLastToken()
+{
+ m_currentToken = m_currentToken == &m_token1 ? &m_token2 : &m_token1;
}
/**
public:
RplToken* nextToken();
void undoLastToken();
+ void undoLastToken2();
+ void saveLastToken();
RplToken* peekNonSpaceToken();
RplToken* nextNonSpaceToken();
size_t maxTokenLength() const;
QString m_idRest2;
RplToken* m_currentToken;
RplToken* m_waitingToken;
+ RplToken* m_waitingToken2;
RplToken m_token1;
RplToken m_token2;
const RplSourcePosition* m_currentPosition;
+ const RplSourcePosition* m_waitingPosition1;
+ const RplSourcePosition* m_waitingPosition2;
int m_maxTokenLength;
QString m_input;
int m_currentCol;
return rc;
}
+/**
+ * @brief Parses a list.
+ *
+ * Syntax:<br>
+ * '[' [<expr_1> [ ',' <expr_2> ...]] ']'
+ *
+ * @precondition '[' is the current token
+ * @postcondition the token behind the ']' is read
+ * @return a node of the abstract syntax tree
+ */
+RplASItem* RplMFParser::parseList()
+{
+ RplASListConstant* rc = new RplASListConstant();
+ rc->setPosition(m_lexer.currentPosition());
+
+ bool again = true;
+ RplToken* token;
+ RplToken* token2;
+ while(again){
+ token = m_lexer.nextNonSpaceToken();
+ if (token->isOperator(O_LBRACKET))
+ again = false;
+ else{
+ m_lexer.saveLastToken();
+ RplASVariant* variant = NULL;
+ token2 = m_lexer.nextNonSpaceToken();
+ if (token2->isOperator(O_COMMA)){
+ switch(token->tokenType()){
+ case TOKEN_NUMBER:
+ variant = new RplASVariant();
+ variant->setInt(token->asInteger());
+ break;
+ case TOKEN_STRING:
+ variant = new RplASVariant();
+ variant->setString(token->toString());
+ break;
+ case TOKEN_REAL:
+ variant = new RplASVariant();
+ variant->setFloat(token->asReal());
+ break;
+ case TOKEN_KEYWORD:
+ switch(token->id()){
+ case K_TRUE:
+ case K_FALSE:
+ variant = new RplASVariant();
+ variant->setBool(token->id() == K_TRUE);
+ break;
+ case K_NONE:
+ variant = new RplASVariant();
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (variant == NULL){
+ m_lexer.undoLastToken2();
+ RplASExprStatement* expr = parseExprStatement();
+ expr->successor(rc->child());
+ rc->setChild(expr);
+ variant = RplASFormula::m_instance.newValueInstance(expr);
+ }
+ }
+ }
+ return rc;
+}
+
+/**
+ * @brief Parses a map.
+ *
+ * Syntax:<br>
+ * '{' [ <string_expr1> ':' <expr_1> [ ',' <string_expr1> ': <expr_2> ...]] '}'
+ *
+ * @precondition '{' is the current token
+ * @postcondition the token behind the '}' is read
+ * @return a node of the abstract syntax tree
+ */
+RplASItem* RplMFParser::parseMap()
+{
+ return NULL;
+}
+
/**
* @brief Parses an operand.
- * An operand is the first and the third part of an binary operation.
- * Examples: constant, variable, method call
+ *
+ * An operand is the first and the third part of a binary operation.
+ * Examples: constant, variable, method call, an expression in parentheses
*
* @return the node with the operand
*/
case TOKEN_OPERATOR:
{
Operator opId = (Operator) token->id();
- if (opId == O_LPARENTH){
+ if (opId == O_LBRACKET){
+ rc = parseList();
+ } else if (opId == O_LBRACE){
+ rc = parseMap();
+ } else if (opId == O_LPARENTH){
rc = parseExpr(level + 1);
token = m_lexer.currentToken();
if(! token->isOperator(O_RPARENT)){
RplASItem* parseModule(const QString& name);
void parse();
RplASItem*parseExprStatement();
+ RplASItem*parseList();
+ RplASItem*parseMap();
protected:
RplASArgument* parseArguments();
RplASItem* parseOperand(int level);
parser.parse();
checkAST("forIt1.txt", __LINE__);
}
+ void listTest(){
+ setSource("List a = [2, 3.14, 1+9, 'hi', a]; List b = [];");
+ RplMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("forIt1.txt", __LINE__);
+ }
virtual void doIt(void) {
+ listTest();
forCTest();
forItTest();
opTest();