]> Some of my projects - anidbudpclient.git/commitdiff
Add RenameParser
authorAPTX <marek321@gmail.com>
Sat, 11 Dec 2010 17:02:19 +0000 (18:02 +0100)
committerAPTX <marek321@gmail.com>
Sat, 11 Dec 2010 17:02:19 +0000 (18:02 +0100)
29 files changed:
anidbudpclient.pro
renameengine/AniAdd/aniadd.pri [new file with mode: 0644]
renameengine/AniAdd/lexer.cpp [new file with mode: 0644]
renameengine/AniAdd/lexer.h [new file with mode: 0644]
renameengine/AniAdd/parser.g [new file with mode: 0644]
renameengine/AniAdd/renamegrammar.cpp [new file with mode: 0644]
renameengine/AniAdd/renamegrammar_p.h [new file with mode: 0644]
renameengine/AniAdd/renameparser.cpp [new file with mode: 0644]
renameengine/AniAdd/renameparser.h [new file with mode: 0644]
renameengine/ECMAScript/ecmascript.pri [new file with mode: 0644]
renameengine/ECMAScript/parser.cpp [new file with mode: 0644]
renameengine/ECMAScript/parser.h [new file with mode: 0644]
renameengine/abstractparser.cpp [new file with mode: 0644]
renameengine/abstractparser.h [new file with mode: 0644]
renameengine/abstractwalk.cpp [new file with mode: 0644]
renameengine/abstractwalk.h [new file with mode: 0644]
renameengine/analyzewalk.cpp [new file with mode: 0644]
renameengine/analyzewalk.h [new file with mode: 0644]
renameengine/ast.cpp [new file with mode: 0644]
renameengine/ast.h [new file with mode: 0644]
renameengine/debugwalk.cpp [new file with mode: 0644]
renameengine/debugwalk.h [new file with mode: 0644]
renameengine/evaluatewalk.cpp [new file with mode: 0644]
renameengine/evaluatewalk.h [new file with mode: 0644]
renameengine/functions.cpp [new file with mode: 0644]
renameengine/functions.h [new file with mode: 0644]
renameengine/parser.pri [new file with mode: 0644]
renameengine/renameengine.cpp [new file with mode: 0644]
renameengine/renameengine.h [new file with mode: 0644]

index 5f01f7e4ba4a19b1757da9921a80bb684b744598..cf6635979bf5aef59fffc15e4741f49e8d9b54f8 100644 (file)
@@ -32,7 +32,7 @@ SOURCES += client.cpp \
     hashproducer.cpp \\r
        hashconsumer.cpp \\r
     clientsentcommandsmodel.cpp \\r
-    clientqueuedcommandsmodel.cpp\r
+       clientqueuedcommandsmodel.cpp\r
 \r
 HEADERS += client.h \\r
     anidbudpclient_global.h \\r
@@ -51,7 +51,7 @@ HEADERS += client.h \
     hashconsumer.h \\r
        circularbuffer.h \\r
     clientsentcommandsmodel.h \\r
-    clientqueuedcommandsmodel.h\r
+       clientqueuedcommandsmodel.h\r
 \r
 CONV_HEADERS += include/AniDBUdpClient/Client \\r
     include/AniDBUdpClient/AbstractCommand \\r
@@ -65,3 +65,39 @@ CONV_HEADERS += include/AniDBUdpClient/Client \
        include/AniDBUdpClient/Hash \\r
        include/AniDBUdpClient/ClientSentCommandsModel \\r
        include/AniDBUdpClient/ClientQueuedCommandsModel\r
+\r
+# RenameParser Files\r
+\r
+SOURCES +=\r
+       renameengine/renameengine.cpp \\r
+       renameengine/functions.cpp \\r
+       renameengine/evaluatewalk.cpp \\r
+       renameengine/debugwalk.cpp \\r
+       renameengine/ast.cpp \\r
+       renameengine/analyzewalk.cpp \\r
+       renameengine/abstractwalk.cpp \\r
+       renameengine/abstractparser.cpp \\r
+       renameengine/AniAdd/renameparser.cpp \\r
+       renameengine/AniAdd/renamegrammar.cpp \\r
+       renameengine/AniAdd/lexer.cpp \\r
+       renameengine/ECMAScript/parser.cpp\r
+\r
+SOURCES +=\r
+       renameengine/renameengine.h \\r
+       renameengine/functions.h \\r
+       renameengine/evaluatewalk.h \\r
+       renameengine/debugwalk.h \\r
+       renameengine/ast.h \\r
+       renameengine/analyzewalk.h \\r
+       renameengine/abstractwalk.h \\r
+       renameengine/abstractparser.h \\r
+       renameengine/AniAdd/renameparser.h \\r
+       renameengine/AniAdd/renamegrammar_p.h \\r
+       renameengine/AniAdd/lexer.h \\r
+       renameengine/ECMAScript/parser.h\r
+\r
+OTHER_FILES += \\r
+       renameengine/parser.pri \\r
+       renameengine/AniAdd/parser.g \\r
+       renameengine/AniAdd/aniadd.pri \\r
+       renameengine/ECMAScript/ecmascript.pri\r
diff --git a/renameengine/AniAdd/aniadd.pri b/renameengine/AniAdd/aniadd.pri
new file mode 100644 (file)
index 0000000..47a92cd
--- /dev/null
@@ -0,0 +1,6 @@
+HEADERS += $$PWD/renameparser.h \
+    $$PWD/renamegrammar_p.h \
+       $$PWD/lexer.h
+SOURCES += $$PWD/renameparser.cpp \
+    $$PWD/renamegrammar.cpp \
+    $$PWD/lexer.cpp \
diff --git a/renameengine/AniAdd/lexer.cpp b/renameengine/AniAdd/lexer.cpp
new file mode 100644 (file)
index 0000000..ca6c1cd
--- /dev/null
@@ -0,0 +1,135 @@
+#include "lexer.h"
+
+#include <QDebug>
+
+namespace RenameParser {
+namespace AniAdd {
+
+Lexer::Lexer()
+{
+       staticInit();
+       init();
+}
+
+void Lexer::init()
+{
+       m_pos = 0;
+
+       m_line = 1;
+       m_column = 1;
+       m_data = "";
+}
+
+void Lexer::lex(const QString &s)
+{
+       init();
+       m_data = s;
+}
+
+bool Lexer::next()
+{
+       m_pos = rx.indexIn(m_data, m_pos);
+
+       if (m_pos == -1)
+       {
+               m_type = 0;
+               return false;
+       }
+#ifdef PARSER_DEBUG
+QString m = rx.cap();
+qDebug() << "TOKEN=" << m;
+#endif
+       m_pos += rx.matchedLength();
+       m_column += rx.matchedLength();
+
+       if (rx.cap() == "\n" || rx.cap()[0] == QChar('#') || rx.cap().left(2) == "//")
+       {
+               ++m_line;
+               m_column = 1;
+               m_type = RenameGrammar::NEWLINE;
+               return true;
+       }
+
+       if (tokenMap.contains(rx.cap()))
+       {
+               m_type = tokenMap.value(rx.cap());
+       }
+       else if (rx.cap()[0] == QChar('"') || rx.cap()[0] == QChar('\''))
+       {
+               m_type = RenameGrammar::STRING;
+       }
+       else
+       {
+               bool ok;
+               rx.cap().toDouble(&ok);
+
+               if (ok)
+                       m_type = RenameGrammar::NUMBER;
+               else
+                       m_type = RenameGrammar::IDENTIFIER;
+       }
+       return true;
+}
+
+QString Lexer::value() const
+{
+       if (m_type == RenameGrammar::STRING)
+               return rx.cap().mid(1, rx.cap().length() - 2);
+       return rx.cap();
+}
+
+int Lexer::type() const
+{
+       return m_type;
+}
+
+int Lexer::line() const
+{
+       return m_line;
+}
+
+int Lexer::column() const
+{
+       return m_column;
+}
+
+int Lexer::pos() const
+{
+       return m_pos;
+}
+
+bool Lexer::end() const
+{
+       return m_pos == -1;
+}
+
+void Lexer::staticInit()
+{
+       if (staticInitialised) return;
+
+       tokenMap[":="]          = RenameGrammar::ASSIGN;
+       tokenMap["="]           = RenameGrammar::EQUALS;
+       tokenMap["%"]           = RenameGrammar::PERCENT;
+       tokenMap["?"]           = RenameGrammar::QUESTION;
+       tokenMap[":"]           = RenameGrammar::DOUBLE_COLON;
+       tokenMap["$"]           = RenameGrammar::DOLLAR;
+       tokenMap[","]           = RenameGrammar::COMMA;
+       tokenMap["("]           = RenameGrammar::LPAREN;
+       tokenMap[")"]           = RenameGrammar::RPAREN;
+       tokenMap["["]           = RenameGrammar::LBRACKET;
+       tokenMap["]"]           = RenameGrammar::RBRACKET;
+       tokenMap["{"]           = RenameGrammar::LCURLY;
+       tokenMap["}"]           = RenameGrammar::RCURLY;
+       tokenMap["if"]          = RenameGrammar::IF;
+       tokenMap["else"]        = RenameGrammar::ELSE;
+
+       staticInitialised = true;
+}
+
+const char *Lexer::regexp = ":=|=|%|\\?|:|\\$|,|\\(|\\)|\\[|\\]|\\{|\\}|\\n|else|if|(:?//|#)[^\\n]*\\n|[^\"\\[\\]:= {}(),%$?\\n]+|\"[^\"]*\"|'[^']*'";
+
+QRegExp Lexer::rx(Lexer::regexp);
+QMap<QString, int> Lexer::tokenMap;
+bool Lexer::staticInitialised = false;
+
+}} // namespace
diff --git a/renameengine/AniAdd/lexer.h b/renameengine/AniAdd/lexer.h
new file mode 100644 (file)
index 0000000..cdc44bd
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef LEXER_H
+#define LEXER_H
+
+#include <QMap>
+#include <QRegExp>
+
+#include "renameparser.h"
+
+namespace RenameParser {
+namespace AniAdd {
+
+#include "renamegrammar_p.h"
+
+
+class Lexer
+{
+public:
+       Lexer();
+
+       void lex(const QString &s);
+
+       bool next();
+
+       QString value() const;
+       int type() const;
+
+       int line() const;
+       int column() const;
+       int pos() const;
+       bool end() const;
+
+private:
+       void init();
+       static void staticInit();
+       static bool staticInitialised;
+
+       int m_type;
+
+       QString m_data;
+       int m_line;
+       int m_column;
+
+       int m_pos;
+       static QRegExp rx;
+       static const char *regexp;
+
+       static QMap<QString, int> tokenMap;
+};
+
+}} // namespace
+
+#endif // LEXER_H
diff --git a/renameengine/AniAdd/parser.g b/renameengine/AniAdd/parser.g
new file mode 100644 (file)
index 0000000..e166607
--- /dev/null
@@ -0,0 +1,780 @@
+%parser         RenameGrammar
+%decl           renameparser.h
+%impl           renameparser.cpp
+
+%expect 5
+
+%token STRING "string"
+%token NUMBER "number"
+%token IDENTIFIER "identifier"
+
+%token ASSIGN ":="
+%token EQUALS "="
+%token PERCENT "%"
+%token QUESTION "?"
+%token DOUBLE_COLON ":"
+%token DOLLAR "$"
+%token COMMA ","
+
+%token LPAREN "("
+%token RPAREN ")"
+%token LBRACKET "["
+%token RBRACKET "]"
+%token LCURLY "{"
+%token RCURLY "}"
+
+%token NEWLINE "newline"
+%token IF "if"
+%token ELSE "else"
+
+%start Program
+
+/:
+#ifndef ANIADDPARSER_H
+#define ANIADDPARSER_H
+
+#include "../abstractparser.h"
+#include "../ast.h"
+#include "renamegrammar_p.h"
+#include "../debugwalk.h"
+#include "../evaluatewalk.h"
+
+#include <QtCore/QVector>
+
+#include <QDebug>
+
+namespace RenameParser {
+
+namespace AniAdd {
+
+using namespace AST;
+
+class Lexer;
+
+class RenameParser : public AbstractParser, protected $table
+{
+public:
+    RenameParser();
+    ~RenameParser();
+
+       bool parse(const QString &string);
+
+       int line() const;
+       int column() const;
+    QString error() const;
+       QString evaluate(Environment &env) const;
+
+private:
+       bool parse(Lexer *lexer);
+
+    void reallocateStack();
+       void cleanup();
+
+       inline QSharedPointer<Node> &sym(int index)
+    { return m_symStack[m_tos + index - 1]; }
+
+    int m_tos;
+    QVector<int> m_stateStack;
+       QVector<QSharedPointer<Node> > m_symStack;
+       int m_line;
+       int m_column;
+    QString m_error;
+    QString m_result;
+
+       Lexer *lexer;
+       QSharedPointer<Node> ast;
+};
+
+}} // namespace
+
+#endif // ANIADDPARSER_H
+
+:/
+
+/.
+#include <QtCore/QDebug>
+#include "renameparser.h"
+#include "lexer.h"
+
+namespace RenameParser {
+namespace AniAdd {
+
+RenameParser::RenameParser()
+{
+       lexer = new Lexer;
+}
+
+RenameParser::~RenameParser()
+{
+       cleanup();
+       delete lexer;
+}
+
+void RenameParser::reallocateStack()
+{
+    int size = m_stateStack.size();
+    if (size == 0)
+        size = 128;
+    else
+        size <<= 1;
+
+    m_symStack.resize(size);
+    m_stateStack.resize(size);
+}
+
+void RenameParser::cleanup()
+{
+       m_symStack.clear();
+       m_stateStack.clear();
+}
+
+int RenameParser::line() const
+{
+       return m_line;
+}
+
+int RenameParser::column() const
+{
+       return m_column;
+}
+
+QString RenameParser::error() const
+{
+    return m_error;
+}
+
+QString RenameParser::evaluate(Environment &env) const
+{
+       if (!ast)
+       {
+               qDebug() << "No AST generated";
+               return "";
+       }
+#ifdef PARSER_DEBUG
+#endif
+       DebugWalk w(ast);
+       Environment envCpy = env;
+       qDebug() << w.walk(envCpy);
+       EvaluateWalk ew(ast);
+       return ew.walk(env);
+}
+
+bool RenameParser::parse(const QString &string)
+{
+       m_renameString = string;
+       lexer->lex(string);
+       return parse(lexer);
+}
+
+bool RenameParser::parse(Lexer *lexer)
+{
+       cleanup();
+
+       const int INITIAL_STATE = 0;
+
+       int yytoken = -1;
+
+       reallocateStack();
+
+       m_tos = 0;
+       m_stateStack[++m_tos] = INITIAL_STATE;
+
+       while (true)
+       {
+               const int state = m_stateStack.at(m_tos);
+               if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
+               {
+                       lexer->next();
+                       yytoken = lexer->type();
+               }
+               int act = t_action (state, yytoken);
+               if (act == ACCEPT_STATE)
+               {
+                       return true;
+               }
+               else if (act > 0)
+               {
+                       if (++m_tos == m_stateStack.size())
+                               reallocateStack();
+                       m_stateStack[m_tos] = act;
+                       yytoken = -1;
+               }
+               else if (act < 0)
+               {
+                       int r = - act - 1;
+
+                       m_tos -= rhs [r];
+                       act = m_stateStack.at(m_tos++);
+
+                       switch (r) {
+./
+
+Program: StatementList ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Program: StatementList ;";
+#endif
+       ast = sym(1);
+} break;
+./
+
+StatementList: Statement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "StatementList: Statement ;";
+#endif
+       StatementList *statementList = new StatementList;
+       statementList->addChild(sym(1));
+       sym(1) = QSharedPointer<Node>(statementList);
+} break;
+./
+
+StatementList: StatementList Statement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "StatementList: StatementList Statement ;";
+#endif
+       if (!sym(2).isNull())
+               sym(1)->addChild(sym(2));
+} break;
+./
+
+Statement: CompoundStatement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: CompoundStatement ;";
+#endif
+} break;
+./
+
+Statement: IfStatement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: IfStatement ;";
+#endif
+} break;
+./
+
+Statement: FunctionDeclarationStatement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: FunctionDeclarationStatement ;";
+#endif
+       } break;
+./
+
+Statement: ExpressionStatement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: ExpressionStatement ;";
+#endif
+       } break;
+./
+
+CompoundStatement: LCURLY StatementList RCURLY ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "BlockStatement: LCURLY StatementList RCURLY ;";
+#endif
+       sym(1) = sym(2);
+} break;
+./
+
+IfStatement: IF LPAREN Expression RPAREN OptionalNewline Statement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "IfStatement: IF LPAREN Expression RPAREN BlockStatement ;";
+#endif
+       IfStatement *ifStatement = new IfStatement;
+       ifStatement->addChild(sym(3));
+       ifStatement->addChild(sym(6));
+       sym(1) = QSharedPointer<Node>(ifStatement);
+       } break;
+./
+
+IfStatement: IF LPAREN Expression RPAREN OptionalNewline Statement ELSE OptionalNewline Statement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "IfStatement: IF LPAREN Expression RPAREN BlockStatement ELSE BlockStatement ;";
+#endif
+       IfStatement *ifStatement = new IfStatement;
+       ifStatement->addChild(sym(3));
+       ifStatement->addChild(sym(6));
+       ifStatement->addChild(sym(9));
+       sym(1) = QSharedPointer<Node>(ifStatement);
+       } break;
+./
+
+FunctionDeclarationStatement: Name LPAREN RPAREN ASSIGN FunctionBody ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationStatement: Name LPAREN RPAREN ASSIGN FunctionBody ;";
+#endif
+
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       QSharedPointer<FunctionDeclarationArgumentList> arglist(new FunctionDeclarationArgumentList);
+
+       Q_ASSERT(sym(5)->type() == Node::Type_FunctionBody);
+       QSharedPointer<FunctionBody> functionBody = qSharedPointerCast<FunctionBody>(sym(5));
+
+       FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist);
+       sym(1) = QSharedPointer<Node>(functionDeclaration);
+       } break;
+./
+
+FunctionDeclarationStatement: Name LPAREN FunctionDeclarationArgumentList RPAREN ASSIGN FunctionBody ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationStatement: Name LPAREN FunctionDeclarationArgumentList RPAREN ASSIGN FunctionBody ;";
+#endif
+
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       Q_ASSERT(sym(3)->type() == Node::Type_FunctionDeclarationArgumentList);
+       QSharedPointer<FunctionDeclarationArgumentList> arglist = qSharedPointerCast<FunctionDeclarationArgumentList>(sym(3));
+
+       Q_ASSERT(sym(6)->type() == Node::Type_FunctionBody);
+       QSharedPointer<FunctionBody> functionBody = qSharedPointerCast<FunctionBody>(sym(6));
+
+       FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist);
+       sym(1) = QSharedPointer<Node>(functionDeclaration);
+       } break;
+./
+
+FunctionBody: ExpressionStatement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionBody: ExpressionStatement ;";
+#endif
+
+       QSharedPointer<Node> functionBody(new FunctionBody);
+       functionBody->addChild(sym(1));
+       sym(1) = functionBody;
+} break;
+./
+
+FunctionBody: CompoundStatement ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionBody: CompoundStatement ;";
+#endif
+
+       QSharedPointer<Node> functionBody(new FunctionBody);
+       functionBody->addChild(sym(1));
+       sym(1) = functionBody;
+} break;
+./
+
+ExpressionStatement: Expression NEWLINE ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "ExpressionStatement: Expression NEWLINE ;";
+#endif
+} break;
+./
+
+ExpressionStatement: NEWLINE ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "ExpressionStatement: Expression NEWLINE ;";
+#endif
+       sym(1) = QSharedPointer<Node>(0);
+} break;
+./
+
+Expression: AssignmentExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Expression: AssignmentExpression ;";
+#endif
+} break;
+./
+
+
+AssignmentExpression: ConditionalExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "AssignmentExpression: ConditionalExpression ;";
+#endif
+} break;
+./
+
+AssignmentExpression: LeftHandSideExpression ASSIGN AssignmentExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "AssignmentExpression: LeftHandSideExpression ASSIGN AssignmentExpression ;";
+#endif
+       Expression *expression = new Expression(Op::Assign);
+       expression->addChild(sym(1));
+       expression->addChild(sym(3));
+       sym(1) = QSharedPointer<Node>(expression);
+} break;
+./
+
+LeftHandSideExpression: Variable ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "LeftHandSideExpression: Variable ;";
+#endif
+} break;
+./
+
+
+ConditionalExpression: AdditiveExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "ConditionalExpression: AdditiveExpression ;";
+#endif
+} break;
+./
+
+ConditionalExpression: AdditiveExpression QUESTION AssignmentExpression DOUBLE_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "ConditionalExpression: AdditiveExpression QUESTION AssignmentExpression DOUBLE_COLON AssignmentExpression ;";
+#endif
+       Expression *cond = new Expression(Op::Conditional);
+       cond->addChild(sym(1));
+       cond->addChild(sym(3));
+       cond->addChild(sym(5));
+       sym(1) = QSharedPointer<Node>(cond);
+       } break;
+./
+
+ConditionalExpression: LCURLY AdditiveExpression QUESTION AssignmentExpression DOUBLE_COLON AssignmentExpression RCURLY ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "ConditionalExpression: AdditiveExpression QUESTION AssignmentExpression DOUBLE_COLON AssignmentExpression ;";
+#endif
+       Expression *cond = new Expression(Op::Conditional);
+       cond->addChild(sym(2));
+       cond->addChild(sym(4));
+       cond->addChild(sym(6));
+       sym(1) = QSharedPointer<Node>(cond);
+       } break;
+./
+
+AdditiveExpression: PrimaryExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "AdditiveExpression: PrimaryExpression ;";
+#endif
+} break;
+./
+
+AdditiveExpression: AdditiveExpression EQUALS PrimaryExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "AdditiveExpression: AdditiveExpression EQUALS PrimaryExpression ;";
+#endif
+       Expression *expression = new Expression(Op::Equals);
+       expression->addChild(sym(1));
+       expression->addChild(sym(3));
+       sym(1) = QSharedPointer<Node>(expression);
+} break;
+./
+
+AdditiveExpression: AdditiveExpression PrimaryExpression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "AdditiveExpression: AdditiveExpression PrimaryExpression ;";
+#endif
+       Expression *expression = new Expression(Op::Concat);
+       expression->addChild(sym(1));
+       expression->addChild(sym(2));
+       sym(1) = QSharedPointer<Node>(expression);
+} break;
+./
+
+PrimaryExpression: Variable ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: Variable ;";
+#endif
+} break;
+./
+
+PrimaryExpression: STRING ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: STRING ;";
+#endif
+       StringLiteral *string = new StringLiteral(lexer->value());
+       sym(1) = QSharedPointer<Node>(string);
+} break;
+./
+
+PrimaryExpression: NUMBER ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: NUMBER ;";
+#endif
+       NumericLiteral *number = new NumericLiteral(lexer->value());
+       sym(1) = QSharedPointer<Node>(number);
+} break;
+./
+
+PrimaryExpression: LPAREN Expression RPAREN ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: LPAREN Expression RPAREN ;";
+#endif
+    sym(1) = sym(2);
+} break;
+./
+
+PrimaryExpression: LBRACKET FunctionArgumentList RBRACKET ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: LBRACKET FunctionArgumentList RBRACKET ;";
+#endif
+
+       if (sym(2)->type() != Node::Type_FunctionArgumentList)
+               qFatal("Cast to FunctionArgumentList failed");
+
+       QSharedPointer<FunctionArgumentList> arglist = qSharedPointerCast<FunctionArgumentList>(sym(2));
+
+       Alternative *alt = new Alternative(arglist);
+       sym(1) = QSharedPointer<Node>(alt);
+} break;
+./
+
+PrimaryExpression: DOLLAR Name LPAREN RPAREN ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: DOLLAR Name LPAREN RPAREN ;";
+#endif
+
+       Q_ASSERT(sym(2)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(2).data();
+
+       QSharedPointer<FunctionArgumentList> arglist(new FunctionArgumentList());
+       FunctionCall *call = new FunctionCall(name->value(), arglist);
+       sym(1) = QSharedPointer<Node>(call);
+
+} break;
+./
+
+PrimaryExpression: DOLLAR Name LPAREN FunctionArgumentList RPAREN ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: DOLLAR Name LPAREN FunctionArgumentList RPAREN ;";
+#endif
+
+       Q_ASSERT(sym(2)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(2).data();
+       
+       if (sym(4)->type() != Node::Type_FunctionArgumentList)
+               qFatal("Cast to FunctionArgumentList failed");
+
+       QSharedPointer<FunctionArgumentList> arglist = qSharedPointerCast<FunctionArgumentList>(sym(4));
+
+       FunctionCall *call = new FunctionCall(name->value(), arglist);
+       sym(1) = QSharedPointer<Node>(call);
+
+} break;
+./
+
+Variable: Name ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Variable: Name ;";
+#endif
+
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       Variable *variable = new Variable(name->value());
+       sym(1) = QSharedPointer<Node>(variable);
+} break;
+./
+
+Variable: PERCENT Name PERCENT;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Variable: PERCENT Name PERCENT ;";
+#endif
+
+       Q_ASSERT(sym(2)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(2).data();
+
+       Variable *variable = new Variable(name->value());
+       sym(1) = QSharedPointer<Node>(variable);
+} break;
+./
+
+FunctionDeclarationArgumentList: FunctionDeclarationArgument ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationArgumentList: FunctionDeclarationArgument ;";
+#endif
+
+       FunctionDeclarationArgumentList *arglist = new FunctionDeclarationArgumentList;
+
+       arglist->addChild(sym(1));
+       sym(1) = QSharedPointer<Node>(arglist);
+} break;
+./
+
+FunctionDeclarationArgumentList: FunctionDeclarationArgumentList COMMA FunctionDeclarationArgument ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationArgumentList: FunctionDeclarationArgumentList COMMA FunctionDeclarationArgument ;";
+#endif
+
+       sym(1)->addChild(sym(3));
+} break;
+./
+
+FunctionArgumentList: Expression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionArgumentList: Expression ;";
+#endif
+       FunctionArgumentList *arglist = new FunctionArgumentList;
+       arglist->addChild(sym(1));
+       sym(1) = QSharedPointer<Node>(arglist);
+} break;
+./
+
+FunctionArgumentList: FunctionArgumentList COMMA Expression ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionArgumentList: FunctionArgumentList COMMA Expression ;";
+#endif
+
+       sym(1)->addChild(sym(3));
+} break;
+./
+
+FunctionDeclarationArgument: Name ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Name: IDENTIFIER ;";
+#endif
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       FunctionDeclarationArgument *arg = new FunctionDeclarationArgument(name->value());
+       sym(1) = QSharedPointer<Node>(arg);
+} break;
+./
+
+Name: IDENTIFIER ;
+/.
+case $rule_number: {
+#ifdef PARSER_DEBUG
+qDebug() << "Name: IDENTIFIER ;";
+#endif
+       Name *name = new Name(lexer->value());
+       sym(1) = QSharedPointer<Node>(name);
+} break;
+./
+
+
+OptionalNewline: ;
+OptionalNewline: OptionalNewline NEWLINE;
+
+/.
+                       } // switch
+
+                       m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT);
+               }
+               else
+               {
+                       int ers = state;
+                       int shifts = 0;
+                       int reduces = 0;
+                       int expected_tokens[3];
+                       for (int tk = 0; tk < TERMINAL_COUNT; ++tk)
+                       {
+                               int k = t_action(ers, tk);
+
+                               if (!k)
+                                       continue;
+                               else if (k < 0)
+                                       ++reduces;
+                               else if (spell[tk])
+                               {
+                                       if (shifts < 3)
+                                               expected_tokens[shifts] = tk;
+                                       ++shifts;
+                               }
+                       }
+
+                       m_line = lexer->line();
+                       m_column = lexer->column();
+                       m_error.clear();
+                       if (shifts && shifts < 3)
+                       {
+                               bool first = true;
+
+                               for (int s = 0; s < shifts; ++s)
+                               {
+                                       if (first)
+                                               m_error += QLatin1String("Expected ");
+                                       else
+                                               m_error += QLatin1String(", ");
+
+                                       first = false;
+                                       m_error += QLatin1String("`");
+                                       m_error += QLatin1String(spell[expected_tokens[s]]);
+                                       m_error += QLatin1String("'");
+                               }
+                               m_error += QString(" on line %1, column %2").arg(m_line).arg(m_column);
+                       }
+                       qDebug() << m_error;
+
+                       return false;
+               }
+       }
+
+       return false;
+}
+
+}} // namespace
+
+./
diff --git a/renameengine/AniAdd/renamegrammar.cpp b/renameengine/AniAdd/renamegrammar.cpp
new file mode 100644 (file)
index 0000000..f70de6c
--- /dev/null
@@ -0,0 +1,200 @@
+// This file was generated by qlalr - DO NOT EDIT!
+#include "renamegrammar_p.h"
+
+const char *const RenameGrammar::spell [] = {
+  "end of file", "string", "number", "identifier", ":=", "=", "%", "?", ":", "$", 
+  ",", "(", ")", "[", "]", "{", "}", "newline", "if", "else", 
+  
+#ifndef QLALR_NO_RENAMEGRAMMAR_DEBUG_INFO
+"Program", "StatementList", "Statement", "CompoundStatement", "IfStatement", "FunctionDeclarationStatement", "ExpressionStatement", "Expression", "OptionalNewline", "Name", 
+  "FunctionBody", "FunctionDeclarationArgumentList", "AssignmentExpression", "ConditionalExpression", "LeftHandSideExpression", "Variable", "AdditiveExpression", "PrimaryExpression", "FunctionArgumentList", "FunctionDeclarationArgument", 
+  "$accept"
+#endif // QLALR_NO_RENAMEGRAMMAR_DEBUG_INFO
+};
+
+const int RenameGrammar::lhs [] = {
+  20, 21, 21, 22, 22, 22, 22, 23, 24, 24, 
+  25, 25, 30, 30, 26, 26, 27, 32, 32, 34, 
+  33, 33, 33, 36, 36, 36, 37, 37, 37, 37, 
+  37, 37, 37, 35, 35, 31, 31, 38, 38, 39, 
+  29, 28, 28, 40};
+
+const int RenameGrammar:: rhs[] = {
+  1, 1, 2, 1, 1, 1, 1, 3, 6, 9, 
+  5, 6, 1, 1, 2, 1, 1, 1, 3, 1, 
+  1, 5, 7, 1, 3, 2, 1, 1, 1, 3, 
+  3, 4, 5, 1, 3, 1, 3, 1, 3, 1, 
+  1, 0, 2, 2};
+
+
+#ifndef QLALR_NO_RENAMEGRAMMAR_DEBUG_INFO
+const int RenameGrammar::rule_info [] = {
+    20, 21
+  , 21, 22
+  , 21, 21, 22
+  , 22, 23
+  , 22, 24
+  , 22, 25
+  , 22, 26
+  , 23, 15, 21, 16
+  , 24, 18, 11, 27, 12, 28, 22
+  , 24, 18, 11, 27, 12, 28, 22, 19, 28, 22
+  , 25, 29, 11, 12, 4, 30
+  , 25, 29, 11, 31, 12, 4, 30
+  , 30, 26
+  , 30, 23
+  , 26, 27, 17
+  , 26, 17
+  , 27, 32
+  , 32, 33
+  , 32, 34, 4, 32
+  , 34, 35
+  , 33, 36
+  , 33, 36, 7, 32, 8, 32
+  , 33, 15, 36, 7, 32, 8, 32, 16
+  , 36, 37
+  , 36, 36, 5, 37
+  , 36, 36, 37
+  , 37, 35
+  , 37, 1
+  , 37, 2
+  , 37, 11, 27, 12
+  , 37, 13, 38, 14
+  , 37, 9, 29, 11, 12
+  , 37, 9, 29, 11, 38, 12
+  , 35, 29
+  , 35, 6, 29, 6
+  , 31, 39
+  , 31, 31, 10, 39
+  , 38, 27
+  , 38, 38, 10, 27
+  , 39, 29
+  , 29, 3
+  , 28
+  , 28, 28, 17
+  , 40, 20, 0};
+
+const int RenameGrammar::rule_index [] = {
+  0, 2, 4, 7, 9, 11, 13, 15, 19, 26, 
+  36, 42, 49, 51, 53, 56, 58, 60, 62, 66, 
+  68, 70, 76, 84, 86, 90, 93, 95, 97, 99, 
+  103, 107, 112, 118, 120, 124, 126, 130, 132, 136, 
+  138, 140, 141, 144};
+#endif // QLALR_NO_RENAMEGRAMMAR_DEBUG_INFO
+
+const int RenameGrammar::action_default [] = {
+  0, 21, 17, 4, 18, 0, 0, 7, 6, 41, 
+  0, 5, 0, 0, 0, 0, 16, 29, 34, 0, 
+  24, 0, 28, 2, 1, 27, 0, 34, 26, 0, 
+  27, 25, 0, 0, 0, 22, 0, 0, 0, 0, 
+  0, 23, 0, 0, 38, 0, 32, 0, 33, 39, 
+  15, 0, 0, 42, 0, 16, 9, 42, 0, 16, 
+  10, 0, 31, 21, 34, 0, 0, 0, 0, 22, 
+  0, 36, 0, 40, 0, 0, 0, 37, 0, 14, 
+  13, 12, 0, 21, 0, 0, 0, 22, 0, 11, 
+  8, 3, 0, 30, 0, 19, 0, 35, 44};
+
+const int RenameGrammar::goto_default [] = {
+  21, 65, 23, 3, 11, 8, 7, 6, 54, 27, 
+  81, 72, 2, 4, 15, 25, 1, 20, 61, 71, 
+  0};
+
+const int RenameGrammar::action_index [] = {
+  184, 165, -20, -20, -20, 6, -9, -20, -20, -20, 
+  -7, -20, 70, 184, 70, 2, -20, -20, 9, 13, 
+  -20, 18, -20, -20, 184, 10, 51, -20, -20, 70, 
+  -20, -20, 7, 51, 70, -20, 89, 70, 5, 70, 
+  -5, -20, 12, 146, -20, 15, -20, 70, -20, -20, 
+  -20, 70, -11, -20, 203, -20, -17, -20, 222, -20, 
+  -20, 32, -20, 38, -6, 241, 70, -8, 70, 1, 
+  19, -20, 23, -20, 8, 0, 3, -20, 127, -20, 
+  -20, -20, 184, 108, 70, 11, 70, 14, 127, -20, 
+  -20, -20, -2, -20, 70, -20, 22, -20, -20, 
+
+  10, 7, -21, -21, -21, -4, -21, -21, -21, -21, 
+  -21, -21, 2, 36, -5, -21, -21, -21, -21, -3, 
+  -21, -21, -21, -21, 27, -21, 29, -21, -21, -8, 
+  -21, -21, -21, 11, -2, -21, 15, 0, -21, 6, 
+  -21, -21, -21, 13, -21, -21, -21, 16, -21, -21, 
+  -21, 1, -21, -21, 41, -21, -21, -1, 12, -21, 
+  -21, -21, -21, 24, -21, 53, 3, -21, 5, -21, 
+  4, -21, -21, -21, -21, 19, -21, -21, 34, -21, 
+  -21, -21, 33, 18, -11, -21, -12, -21, 48, -21, 
+  -21, -21, -21, -21, -9, -21, -21, -21, -21};
+
+const int RenameGrammar::action_info [] = {
+  68, 53, 57, 9, 51, 70, 94, 78, 50, 9, 
+  93, 41, 88, 39, -20, 34, 9, 41, 98, 86, 
+  70, 0, 9, 43, 0, 47, 0, 48, 97, 0, 
+  41, 74, 0, 75, 0, 76, 0, 0, 0, 22, 
+  17, 9, 47, 26, 19, 66, 62, 5, 0, 14, 
+  0, 12, 22, 17, 9, 0, 0, 19, 0, 0, 
+  5, 0, 14, 0, 12, 0, 0, 0, 0, 0, 
+  0, 22, 17, 9, 0, 0, 19, 0, 0, 5, 
+  0, 14, 0, 12, 0, 33, 0, 0, 0, 0, 
+  22, 17, 9, 0, 26, 19, 37, 0, 5, 0, 
+  14, 0, 12, 0, 0, 0, 0, 0, 0, 22, 
+  17, 9, 0, 26, 19, 84, 0, 5, 0, 14, 
+  0, 12, 0, 0, 0, 0, 0, 0, 22, 17, 
+  9, 0, 0, 19, 0, 0, 5, 0, 14, 0, 
+  12, 0, 82, 0, 16, 0, 0, 22, 17, 9, 
+  0, 0, 19, 0, 0, 5, 0, 14, 46, 12, 
+  0, 33, 0, 0, 0, 0, 22, 17, 9, 0, 
+  26, 19, 29, 0, 5, 0, 14, 0, 12, 0, 
+  0, 0, 0, 0, 0, 22, 17, 9, 0, 0, 
+  19, 0, 0, 5, 0, 14, 0, 12, 0, 13, 
+  0, 16, 10, 0, 22, 17, 9, 0, 0, 19, 
+  0, 0, 5, 0, 14, 0, 12, 0, 13, 0, 
+  55, 10, 0, 22, 17, 9, 0, 0, 19, 0, 
+  0, 5, 0, 14, 0, 12, 0, 13, 0, 59, 
+  10, 0, 22, 17, 9, 0, 0, 19, 0, 0, 
+  5, 0, 14, 0, 12, 0, 13, 90, 16, 10, 
+  0, 
+
+  87, 85, 92, 95, 32, 42, 96, 58, 52, 44, 
+  35, 24, 38, 73, 60, 67, 0, 69, 40, 18, 
+  44, 18, 30, 49, 28, 0, 30, 36, 73, 91, 
+  30, 45, 28, 30, 0, 28, 18, 79, 77, 30, 
+  80, 28, 18, 56, 30, 64, 31, 0, 0, 83, 
+  18, 79, 63, 0, 80, 91, 0, 0, 89, 0, 
+  0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0};
+
+const int RenameGrammar::action_check [] = {
+  8, 12, 19, 3, 11, 11, 4, 4, 17, 3, 
+  12, 16, 4, 8, 4, 8, 3, 16, 0, 8, 
+  11, -1, 3, 11, -1, 10, -1, 12, 6, -1, 
+  16, 12, -1, 10, -1, 12, -1, -1, -1, 1, 
+  2, 3, 10, 5, 6, 7, 14, 9, -1, 11, 
+  -1, 13, 1, 2, 3, -1, -1, 6, -1, -1, 
+  9, -1, 11, -1, 13, -1, -1, -1, -1, -1, 
+  -1, 1, 2, 3, -1, -1, 6, -1, -1, 9, 
+  -1, 11, -1, 13, -1, 15, -1, -1, -1, -1, 
+  1, 2, 3, -1, 5, 6, 7, -1, 9, -1, 
+  11, -1, 13, -1, -1, -1, -1, -1, -1, 1, 
+  2, 3, -1, 5, 6, 7, -1, 9, -1, 11, 
+  -1, 13, -1, -1, -1, -1, -1, -1, 1, 2, 
+  3, -1, -1, 6, -1, -1, 9, -1, 11, -1, 
+  13, -1, 15, -1, 17, -1, -1, 1, 2, 3, 
+  -1, -1, 6, -1, -1, 9, -1, 11, 12, 13, 
+  -1, 15, -1, -1, -1, -1, 1, 2, 3, -1, 
+  5, 6, 7, -1, 9, -1, 11, -1, 13, -1, 
+  -1, -1, -1, -1, -1, 1, 2, 3, -1, -1, 
+  6, -1, -1, 9, -1, 11, -1, 13, -1, 15, 
+  -1, 17, 18, -1, 1, 2, 3, -1, -1, 6, 
+  -1, -1, 9, -1, 11, -1, 13, -1, 15, -1, 
+  17, 18, -1, 1, 2, 3, -1, -1, 6, -1, 
+  -1, 9, -1, 11, -1, 13, -1, 15, -1, 17, 
+  18, -1, 1, 2, 3, -1, -1, 6, -1, -1, 
+  9, -1, 11, -1, 13, -1, 15, 16, 17, 18, 
+  -1, 
+
+  12, 12, 7, 12, 12, 9, 9, 8, 7, 7, 
+  12, 1, 12, 9, 2, 12, -1, 12, 12, 9, 
+  7, 9, 15, 7, 17, -1, 15, 16, 9, 2, 
+  15, 18, 17, 15, -1, 17, 9, 3, 19, 15, 
+  6, 17, 9, 2, 15, 9, 17, -1, -1, 16, 
+  9, 3, 16, -1, 6, 2, -1, -1, 10, -1, 
+  -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1};
+
diff --git a/renameengine/AniAdd/renamegrammar_p.h b/renameengine/AniAdd/renamegrammar_p.h
new file mode 100644 (file)
index 0000000..e5193cd
--- /dev/null
@@ -0,0 +1,83 @@
+// This file was generated by qlalr - DO NOT EDIT!
+#ifndef RENAMEGRAMMAR_P_H
+#define RENAMEGRAMMAR_P_H
+
+class RenameGrammar
+{
+public:
+  enum {
+    EOF_SYMBOL = 0,
+    ASSIGN = 4,
+    COMMA = 10,
+    DOLLAR = 9,
+    DOUBLE_COLON = 8,
+    ELSE = 19,
+    EQUALS = 5,
+    IDENTIFIER = 3,
+    IF = 18,
+    LBRACKET = 13,
+    LCURLY = 15,
+    LPAREN = 11,
+    NEWLINE = 17,
+    NUMBER = 2,
+    PERCENT = 6,
+    QUESTION = 7,
+    RBRACKET = 14,
+    RCURLY = 16,
+    RPAREN = 12,
+    STRING = 1,
+
+    ACCEPT_STATE = 98,
+    RULE_COUNT = 44,
+    STATE_COUNT = 99,
+    TERMINAL_COUNT = 20,
+    NON_TERMINAL_COUNT = 21,
+
+    GOTO_INDEX_OFFSET = 99,
+    GOTO_INFO_OFFSET = 261,
+    GOTO_CHECK_OFFSET = 261
+  };
+
+  static const char  *const spell [];
+  static const int            lhs [];
+  static const int            rhs [];
+
+#ifndef QLALR_NO_RENAMEGRAMMAR_DEBUG_INFO
+  static const int     rule_index [];
+  static const int      rule_info [];
+#endif // QLALR_NO_RENAMEGRAMMAR_DEBUG_INFO
+
+  static const int   goto_default [];
+  static const int action_default [];
+  static const int   action_index [];
+  static const int    action_info [];
+  static const int   action_check [];
+
+  static inline int nt_action (int state, int nt)
+  {
+    const int *const goto_index = &action_index [GOTO_INDEX_OFFSET];
+    const int *const goto_check = &action_check [GOTO_CHECK_OFFSET];
+
+    const int yyn = goto_index [state] + nt;
+
+    if (yyn < 0 || goto_check [yyn] != nt)
+      return goto_default [nt];
+
+    const int *const goto_info = &action_info [GOTO_INFO_OFFSET];
+    return goto_info [yyn];
+  }
+
+  static inline int t_action (int state, int token)
+  {
+    const int yyn = action_index [state] + token;
+
+    if (yyn < 0 || action_check [yyn] != token)
+      return - action_default [state];
+
+    return action_info [yyn];
+  }
+};
+
+
+#endif // RENAMEGRAMMAR_P_H
+
diff --git a/renameengine/AniAdd/renameparser.cpp b/renameengine/AniAdd/renameparser.cpp
new file mode 100644 (file)
index 0000000..e1b1c0d
--- /dev/null
@@ -0,0 +1,642 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+#line 94 "parser.g"
+
+#include <QtCore/QDebug>
+#include "renameparser.h"
+#include "lexer.h"
+
+namespace RenameParser {
+namespace AniAdd {
+
+RenameParser::RenameParser()
+{
+       lexer = new Lexer;
+}
+
+RenameParser::~RenameParser()
+{
+       cleanup();
+       delete lexer;
+}
+
+void RenameParser::reallocateStack()
+{
+    int size = m_stateStack.size();
+    if (size == 0)
+        size = 128;
+    else
+        size <<= 1;
+
+    m_symStack.resize(size);
+    m_stateStack.resize(size);
+}
+
+void RenameParser::cleanup()
+{
+       m_symStack.clear();
+       m_stateStack.clear();
+}
+
+int RenameParser::line() const
+{
+       return m_line;
+}
+
+int RenameParser::column() const
+{
+       return m_column;
+}
+
+QString RenameParser::error() const
+{
+    return m_error;
+}
+
+QString RenameParser::evaluate(Environment &env) const
+{
+       if (!ast)
+       {
+               qDebug() << "No AST generated";
+               return "";
+       }
+#ifdef PARSER_DEBUG
+#endif
+/*     DebugWalk w(ast);
+       Environment envCpy = env;
+       qDebug() << w.walk(envCpy);
+*/     EvaluateWalk ew(ast);
+       return ew.walk(env);
+}
+
+bool RenameParser::parse(const QString &string)
+{
+       m_renameString = string;
+       lexer->lex(string);
+       return parse(lexer);
+}
+
+bool RenameParser::parse(Lexer *lexer)
+{
+       cleanup();
+
+       const int INITIAL_STATE = 0;
+
+       int yytoken = -1;
+
+       reallocateStack();
+
+       m_tos = 0;
+       m_stateStack[++m_tos] = INITIAL_STATE;
+
+       while (true)
+       {
+               const int state = m_stateStack.at(m_tos);
+               if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
+               {
+                       lexer->next();
+                       yytoken = lexer->type();
+               }
+               int act = t_action (state, yytoken);
+               if (act == ACCEPT_STATE)
+               {
+                       return true;
+               }
+               else if (act > 0)
+               {
+                       if (++m_tos == m_stateStack.size())
+                               reallocateStack();
+                       m_stateStack[m_tos] = act;
+                       yytoken = -1;
+               }
+               else if (act < 0)
+               {
+                       int r = - act - 1;
+
+                       m_tos -= rhs [r];
+                       act = m_stateStack.at(m_tos++);
+
+                       switch (r) {
+
+#line 213 "parser.g"
+
+case 0: {
+#ifdef PARSER_DEBUG
+qDebug() << "Program: StatementList ;";
+#endif
+       ast = sym(1);
+} break;
+
+#line 223 "parser.g"
+
+case 1: {
+#ifdef PARSER_DEBUG
+qDebug() << "StatementList: Statement ;";
+#endif
+       StatementList *statementList = new StatementList;
+       statementList->addChild(sym(1));
+       sym(1) = QSharedPointer<Node>(statementList);
+} break;
+
+#line 235 "parser.g"
+
+case 2: {
+#ifdef PARSER_DEBUG
+qDebug() << "StatementList: StatementList Statement ;";
+#endif
+       if (!sym(2).isNull())
+               sym(1)->addChild(sym(2));
+} break;
+
+#line 246 "parser.g"
+
+case 3: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: CompoundStatement ;";
+#endif
+} break;
+
+#line 255 "parser.g"
+
+case 4: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: IfStatement ;";
+#endif
+} break;
+
+#line 264 "parser.g"
+
+case 5: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: FunctionDeclarationStatement ;";
+#endif
+       } break;
+
+#line 273 "parser.g"
+
+case 6: {
+#ifdef PARSER_DEBUG
+qDebug() << "Statement: ExpressionStatement ;";
+#endif
+       } break;
+
+#line 282 "parser.g"
+
+case 7: {
+#ifdef PARSER_DEBUG
+qDebug() << "BlockStatement: LCURLY StatementList RCURLY ;";
+#endif
+       sym(1) = sym(2);
+} break;
+
+#line 292 "parser.g"
+
+case 8: {
+#ifdef PARSER_DEBUG
+qDebug() << "IfStatement: IF LPAREN Expression RPAREN BlockStatement ;";
+#endif
+       IfStatement *ifStatement = new IfStatement;
+       ifStatement->addChild(sym(3));
+       ifStatement->addChild(sym(6));
+       sym(1) = QSharedPointer<Node>(ifStatement);
+       } break;
+
+#line 305 "parser.g"
+
+case 9: {
+#ifdef PARSER_DEBUG
+qDebug() << "IfStatement: IF LPAREN Expression RPAREN BlockStatement ELSE BlockStatement ;";
+#endif
+       IfStatement *ifStatement = new IfStatement;
+       ifStatement->addChild(sym(3));
+       ifStatement->addChild(sym(6));
+       ifStatement->addChild(sym(9));
+       sym(1) = QSharedPointer<Node>(ifStatement);
+       } break;
+
+#line 319 "parser.g"
+
+case 10: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationStatement: Name LPAREN RPAREN ASSIGN FunctionBody ;";
+#endif
+
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       QSharedPointer<FunctionDeclarationArgumentList> arglist(new FunctionDeclarationArgumentList);
+
+       Q_ASSERT(sym(5)->type() == Node::Type_FunctionBody);
+       QSharedPointer<FunctionBody> functionBody = qSharedPointerCast<FunctionBody>(sym(5));
+
+       FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist);
+       sym(1) = QSharedPointer<Node>(functionDeclaration);
+       } break;
+
+#line 339 "parser.g"
+
+case 11: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationStatement: Name LPAREN FunctionDeclarationArgumentList RPAREN ASSIGN FunctionBody ;";
+#endif
+
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       Q_ASSERT(sym(3)->type() == Node::Type_FunctionDeclarationArgumentList);
+       QSharedPointer<FunctionDeclarationArgumentList> arglist = qSharedPointerCast<FunctionDeclarationArgumentList>(sym(3));
+
+       Q_ASSERT(sym(6)->type() == Node::Type_FunctionBody);
+       QSharedPointer<FunctionBody> functionBody = qSharedPointerCast<FunctionBody>(sym(6));
+
+       FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist);
+       sym(1) = QSharedPointer<Node>(functionDeclaration);
+       } break;
+
+#line 360 "parser.g"
+
+case 12: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionBody: ExpressionStatement ;";
+#endif
+
+       QSharedPointer<Node> functionBody(new FunctionBody);
+       functionBody->addChild(sym(1));
+       sym(1) = functionBody;
+} break;
+
+#line 373 "parser.g"
+
+case 13: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionBody: CompoundStatement ;";
+#endif
+
+       QSharedPointer<Node> functionBody(new FunctionBody);
+       functionBody->addChild(sym(1));
+       sym(1) = functionBody;
+} break;
+
+#line 386 "parser.g"
+
+case 14: {
+#ifdef PARSER_DEBUG
+qDebug() << "ExpressionStatement: Expression NEWLINE ;";
+#endif
+} break;
+
+#line 395 "parser.g"
+
+case 15: {
+#ifdef PARSER_DEBUG
+qDebug() << "ExpressionStatement: Expression NEWLINE ;";
+#endif
+       sym(1) = QSharedPointer<Node>(0);
+} break;
+
+#line 405 "parser.g"
+
+case 16: {
+#ifdef PARSER_DEBUG
+qDebug() << "Expression: AssignmentExpression ;";
+#endif
+} break;
+
+#line 415 "parser.g"
+
+case 17: {
+#ifdef PARSER_DEBUG
+qDebug() << "AssignmentExpression: ConditionalExpression ;";
+#endif
+} break;
+
+#line 424 "parser.g"
+
+case 18: {
+#ifdef PARSER_DEBUG
+qDebug() << "AssignmentExpression: LeftHandSideExpression ASSIGN AssignmentExpression ;";
+#endif
+       Expression *expression = new Expression(Op::Assign);
+       expression->addChild(sym(1));
+       expression->addChild(sym(3));
+       sym(1) = QSharedPointer<Node>(expression);
+} break;
+
+#line 437 "parser.g"
+
+case 19: {
+#ifdef PARSER_DEBUG
+qDebug() << "LeftHandSideExpression: Variable ;";
+#endif
+} break;
+
+#line 447 "parser.g"
+
+case 20: {
+#ifdef PARSER_DEBUG
+qDebug() << "ConditionalExpression: AdditiveExpression ;";
+#endif
+} break;
+
+#line 456 "parser.g"
+
+case 21: {
+#ifdef PARSER_DEBUG
+qDebug() << "ConditionalExpression: AdditiveExpression QUESTION AssignmentExpression DOUBLE_COLON AssignmentExpression ;";
+#endif
+       Expression *cond = new Expression(Op::Conditional);
+       cond->addChild(sym(1));
+       cond->addChild(sym(3));
+       cond->addChild(sym(5));
+       sym(1) = QSharedPointer<Node>(cond);
+       } break;
+
+#line 470 "parser.g"
+
+case 22: {
+#ifdef PARSER_DEBUG
+qDebug() << "ConditionalExpression: AdditiveExpression QUESTION AssignmentExpression DOUBLE_COLON AssignmentExpression ;";
+#endif
+       Expression *cond = new Expression(Op::Conditional);
+       cond->addChild(sym(2));
+       cond->addChild(sym(4));
+       cond->addChild(sym(6));
+       sym(1) = QSharedPointer<Node>(cond);
+       } break;
+
+#line 484 "parser.g"
+
+case 23: {
+#ifdef PARSER_DEBUG
+qDebug() << "AdditiveExpression: PrimaryExpression ;";
+#endif
+} break;
+
+#line 493 "parser.g"
+
+case 24: {
+#ifdef PARSER_DEBUG
+qDebug() << "AdditiveExpression: AdditiveExpression EQUALS PrimaryExpression ;";
+#endif
+       Expression *expression = new Expression(Op::Equals);
+       expression->addChild(sym(1));
+       expression->addChild(sym(3));
+       sym(1) = QSharedPointer<Node>(expression);
+} break;
+
+#line 506 "parser.g"
+
+case 25: {
+#ifdef PARSER_DEBUG
+qDebug() << "AdditiveExpression: AdditiveExpression PrimaryExpression ;";
+#endif
+       Expression *expression = new Expression(Op::Concat);
+       expression->addChild(sym(1));
+       expression->addChild(sym(2));
+       sym(1) = QSharedPointer<Node>(expression);
+} break;
+
+#line 519 "parser.g"
+
+case 26: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: Variable ;";
+#endif
+} break;
+
+#line 528 "parser.g"
+
+case 27: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: STRING ;";
+#endif
+       StringLiteral *string = new StringLiteral(lexer->value());
+       sym(1) = QSharedPointer<Node>(string);
+} break;
+
+#line 539 "parser.g"
+
+case 28: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: NUMBER ;";
+#endif
+       NumericLiteral *number = new NumericLiteral(lexer->value());
+       sym(1) = QSharedPointer<Node>(number);
+} break;
+
+#line 550 "parser.g"
+
+case 29: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: LPAREN Expression RPAREN ;";
+#endif
+    sym(1) = sym(2);
+} break;
+
+#line 560 "parser.g"
+
+case 30: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: LBRACKET FunctionArgumentList RBRACKET ;";
+#endif
+
+       if (sym(2)->type() != Node::Type_FunctionArgumentList)
+               qFatal("Cast to FunctionArgumentList failed");
+
+       QSharedPointer<FunctionArgumentList> arglist = qSharedPointerCast<FunctionArgumentList>(sym(2));
+
+       Alternative *alt = new Alternative(arglist);
+       sym(1) = QSharedPointer<Node>(alt);
+} break;
+
+#line 577 "parser.g"
+
+case 31: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: DOLLAR Name LPAREN RPAREN ;";
+#endif
+
+       Q_ASSERT(sym(2)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(2).data();
+
+       QSharedPointer<FunctionArgumentList> arglist(new FunctionArgumentList());
+       FunctionCall *call = new FunctionCall(name->value(), arglist);
+       sym(1) = QSharedPointer<Node>(call);
+
+} break;
+
+#line 594 "parser.g"
+
+case 32: {
+#ifdef PARSER_DEBUG
+qDebug() << "PrimaryExpression: DOLLAR Name LPAREN FunctionArgumentList RPAREN ;";
+#endif
+
+       Q_ASSERT(sym(2)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(2).data();
+       
+       if (sym(4)->type() != Node::Type_FunctionArgumentList)
+               qFatal("Cast to FunctionArgumentList failed");
+
+       QSharedPointer<FunctionArgumentList> arglist = qSharedPointerCast<FunctionArgumentList>(sym(4));
+
+       FunctionCall *call = new FunctionCall(name->value(), arglist);
+       sym(1) = QSharedPointer<Node>(call);
+
+} break;
+
+#line 615 "parser.g"
+
+case 33: {
+#ifdef PARSER_DEBUG
+qDebug() << "Variable: Name ;";
+#endif
+
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       Variable *variable = new Variable(name->value());
+       sym(1) = QSharedPointer<Node>(variable);
+} break;
+
+#line 630 "parser.g"
+
+case 34: {
+#ifdef PARSER_DEBUG
+qDebug() << "Variable: PERCENT Name PERCENT ;";
+#endif
+
+       Q_ASSERT(sym(2)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(2).data();
+
+       Variable *variable = new Variable(name->value());
+       sym(1) = QSharedPointer<Node>(variable);
+} break;
+
+#line 645 "parser.g"
+
+case 35: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationArgumentList: FunctionDeclarationArgument ;";
+#endif
+
+       FunctionDeclarationArgumentList *arglist = new FunctionDeclarationArgumentList;
+
+       arglist->addChild(sym(1));
+       sym(1) = QSharedPointer<Node>(arglist);
+} break;
+
+#line 659 "parser.g"
+
+case 36: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionDeclarationArgumentList: FunctionDeclarationArgumentList COMMA FunctionDeclarationArgument ;";
+#endif
+
+       sym(1)->addChild(sym(3));
+} break;
+
+#line 670 "parser.g"
+
+case 37: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionArgumentList: Expression ;";
+#endif
+       FunctionArgumentList *arglist = new FunctionArgumentList;
+       arglist->addChild(sym(1));
+       sym(1) = QSharedPointer<Node>(arglist);
+} break;
+
+#line 682 "parser.g"
+
+case 38: {
+#ifdef PARSER_DEBUG
+qDebug() << "FunctionArgumentList: FunctionArgumentList COMMA Expression ;";
+#endif
+
+       sym(1)->addChild(sym(3));
+} break;
+
+#line 693 "parser.g"
+
+case 39: {
+#ifdef PARSER_DEBUG
+qDebug() << "Name: IDENTIFIER ;";
+#endif
+       Q_ASSERT(sym(1)->type() == Node::Type_Name);
+       Name *name = (Name *) sym(1).data();
+
+       FunctionDeclarationArgument *arg = new FunctionDeclarationArgument(name->value());
+       sym(1) = QSharedPointer<Node>(arg);
+} break;
+
+#line 707 "parser.g"
+
+case 40: {
+#ifdef PARSER_DEBUG
+qDebug() << "Name: IDENTIFIER ;";
+#endif
+       Name *name = new Name(lexer->value());
+       sym(1) = QSharedPointer<Node>(name);
+} break;
+
+#line 721 "parser.g"
+
+                       } // switch
+
+                       m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT);
+               }
+               else
+               {
+                       int ers = state;
+                       int shifts = 0;
+                       int reduces = 0;
+                       int expected_tokens[3];
+                       for (int tk = 0; tk < TERMINAL_COUNT; ++tk)
+                       {
+                               int k = t_action(ers, tk);
+
+                               if (!k)
+                                       continue;
+                               else if (k < 0)
+                                       ++reduces;
+                               else if (spell[tk])
+                               {
+                                       if (shifts < 3)
+                                               expected_tokens[shifts] = tk;
+                                       ++shifts;
+                               }
+                       }
+
+                       m_line = lexer->line();
+                       m_column = lexer->column();
+                       m_error.clear();
+                       if (shifts && shifts < 3)
+                       {
+                               bool first = true;
+
+                               for (int s = 0; s < shifts; ++s)
+                               {
+                                       if (first)
+                                               m_error += QLatin1String("Expected ");
+                                       else
+                                               m_error += QLatin1String(", ");
+
+                                       first = false;
+                                       m_error += QLatin1String("`");
+                                       m_error += QLatin1String(spell[expected_tokens[s]]);
+                                       m_error += QLatin1String("'");
+                               }
+                               m_error += QString(" on line %1, column %2").arg(m_line).arg(m_column);
+                       }
+                       qDebug() << m_error;
+
+                       return false;
+               }
+       }
+
+       return false;
+}
+
+}} // namespace
+
diff --git a/renameengine/AniAdd/renameparser.h b/renameengine/AniAdd/renameparser.h
new file mode 100644 (file)
index 0000000..e8327cd
--- /dev/null
@@ -0,0 +1,63 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+#line 32 "parser.g"
+
+#ifndef ANIADDPARSER_H
+#define ANIADDPARSER_H
+
+#include "../abstractparser.h"
+#include "../ast.h"
+#include "renamegrammar_p.h"
+#include "../debugwalk.h"
+#include "../evaluatewalk.h"
+
+#include <QtCore/QVector>
+
+#include <QDebug>
+
+namespace RenameParser {
+
+namespace AniAdd {
+
+using namespace AST;
+
+class Lexer;
+
+class RenameParser : public AbstractParser, protected RenameGrammar
+{
+public:
+    RenameParser();
+    ~RenameParser();
+
+       bool parse(const QString &string);
+
+       int line() const;
+       int column() const;
+    QString error() const;
+       QString evaluate(Environment &env) const;
+
+private:
+       bool parse(Lexer *lexer);
+
+    void reallocateStack();
+       void cleanup();
+
+       inline QSharedPointer<Node> &sym(int index)
+    { return m_symStack[m_tos + index - 1]; }
+
+    int m_tos;
+    QVector<int> m_stateStack;
+       QVector<QSharedPointer<Node> > m_symStack;
+       int m_line;
+       int m_column;
+    QString m_error;
+    QString m_result;
+
+       Lexer *lexer;
+       QSharedPointer<Node> ast;
+};
+
+}} // namespace
+
+#endif // ANIADDPARSER_H
+
diff --git a/renameengine/ECMAScript/ecmascript.pri b/renameengine/ECMAScript/ecmascript.pri
new file mode 100644 (file)
index 0000000..f604134
--- /dev/null
@@ -0,0 +1,3 @@
+QT *= script
+HEADERS += $$PWD/parser.h
+SOURCES += $$PWD/parser.cpp
diff --git a/renameengine/ECMAScript/parser.cpp b/renameengine/ECMAScript/parser.cpp
new file mode 100644 (file)
index 0000000..9ab685b
--- /dev/null
@@ -0,0 +1,98 @@
+#include "parser.h"
+
+#include <QScriptValueIterator>
+
+namespace RenameParser {
+namespace ECMAScript {
+
+QScriptValue RenameEngine2QtScriptHelper(QScriptContext *context, QScriptEngine *engine, void *arg)
+{
+       Q_UNUSED(engine);
+
+       RenameFunction func = (RenameFunction) arg;
+
+       QStringList args;
+       for (int i = 0; i < context->argumentCount(); ++i)
+               args << context->argument(i).toString();
+
+       return QScriptValue(func(args));
+}
+
+Parser::Parser() : AbstractParser()
+{
+       m_line = 0;
+       m_column = 0;
+}
+
+
+bool Parser::parse(const QString &string)
+{
+       m_error = "";
+       m_line = 0;
+       m_column = 0;
+
+       m_renameString = string;
+       QScriptSyntaxCheckResult checkResult = engine.checkSyntax(string);
+
+       if (checkResult.state() == QScriptSyntaxCheckResult::Valid)
+       {
+               program = string;
+               return true;
+       }
+       m_error = checkResult.errorMessage();
+       m_line = checkResult.errorLineNumber();
+       m_column = checkResult.errorColumnNumber();
+
+       return false;
+}
+
+QString Parser::evaluate(Environment &env) const
+{
+       QScriptContext *fct = engine.pushContext();
+
+       foreach (const QString &funcName, RenameEngine::registeredFunctions())
+       {
+               fct->activationObject().setProperty(funcName,
+                       engine.newFunction(
+                                       &RenameEngine2QtScriptHelper, RenameEngine::function(funcName)));
+       }
+
+       QScriptContext *ct = engine.pushContext();
+
+       for (Environment::const_iterator i = env.constBegin(); i != env.constEnd(); ++i)
+       {
+               ct->activationObject().setProperty(i.key(), i.value());
+       }
+
+       QString ret = engine.evaluate(program).toString();
+
+       QScriptValueIterator it(ct->activationObject());
+
+       while (it.hasNext())
+       {
+               it.next();
+               env[it.name()] = it.value().toString();
+       }
+
+       engine.popContext();
+       engine.popContext();
+
+       return ret;
+}
+
+QString Parser::error() const
+{
+       return m_error;
+}
+
+int Parser::line() const
+{
+       return m_line;
+}
+
+int Parser::column() const
+{
+       return m_column;
+}
+
+}} // namespace
diff --git a/renameengine/ECMAScript/parser.h b/renameengine/ECMAScript/parser.h
new file mode 100644 (file)
index 0000000..10d0580
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef ECMASCRIPTPARSER_H
+#define ECMASCRIPTPARSER_H
+
+#include <QScriptEngine>
+#include <QScriptSyntaxCheckResult>
+#include "../abstractparser.h"
+#include "../renameengine.h"
+
+namespace RenameParser {
+namespace ECMAScript {
+
+class Parser : public AbstractParser
+{
+public:
+       Parser();
+
+       bool parse(const QString &string);
+
+       QString evaluate(Environment &env) const;
+
+       QString error() const;
+       int line() const;
+       int column() const;
+
+private:
+       mutable QScriptEngine engine;
+       QScriptProgram program;
+       QString m_error;
+       int m_line;
+       int m_column;
+};
+
+}} // namespace
+
+#endif // ECMASCRIPTPARSER_H
diff --git a/renameengine/abstractparser.cpp b/renameengine/abstractparser.cpp
new file mode 100644 (file)
index 0000000..97cd47a
--- /dev/null
@@ -0,0 +1,28 @@
+#include "abstractparser.h"
+
+namespace RenameParser {
+
+AbstractParser::AbstractParser()
+{
+}
+
+AbstractParser::~AbstractParser()
+{
+}
+
+QString AbstractParser::renameString() const
+{
+       return m_renameString;
+}
+
+int AbstractParser::line() const
+{
+       return 0;
+}
+
+int AbstractParser::column() const
+{
+       return 0;
+}
+
+} // namespace
diff --git a/renameengine/abstractparser.h b/renameengine/abstractparser.h
new file mode 100644 (file)
index 0000000..dc30190
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef ABSTRACTPARSER_H
+#define ABSTRACTPARSER_H
+
+#include <QString>
+#include <QMap>
+
+namespace RenameParser {
+
+typedef QMap<QString, QString> Environment;
+
+class AbstractParser
+{
+public:
+       AbstractParser();
+       virtual ~AbstractParser();
+
+       virtual QString renameString() const;
+       virtual bool parse(const QString &string) = 0;
+
+       virtual QString evaluate(Environment &env) const = 0;
+
+       virtual QString error() const = 0;
+       virtual int line() const;
+       virtual int column() const;
+
+protected:
+       QString m_renameString;
+};
+
+} // namespace
+
+#endif // ABSTRACTPARSER_H
diff --git a/renameengine/abstractwalk.cpp b/renameengine/abstractwalk.cpp
new file mode 100644 (file)
index 0000000..e65550c
--- /dev/null
@@ -0,0 +1,15 @@
+#include "abstractwalk.h"
+
+namespace RenameParser {
+
+AbstractWalk::AbstractWalk(QSharedPointer<AST::Node> ast)
+{
+       this->ast = ast;
+}
+
+QString AbstractWalk::walk(Environment &)
+{
+       return "";
+}
+
+} // namespace RenameParser
diff --git a/renameengine/abstractwalk.h b/renameengine/abstractwalk.h
new file mode 100644 (file)
index 0000000..3c06b50
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef ABSTRACTWALK_H
+#define ABSTRACTWALK_H
+
+#include "ast.h"
+#include <QSharedPointer>
+#include <QMap>
+
+namespace RenameParser {
+
+typedef QMap<QString, QString> Environment;
+
+class AbstractWalk
+{
+public:
+       AbstractWalk(QSharedPointer<AST::Node> ast);
+
+       virtual QString walk(Environment &env);
+
+       QSharedPointer<AST::Node> ast;
+};
+
+} // namespace RenameParser
+
+#endif // ABSTRACTWALK_H
diff --git a/renameengine/analyzewalk.cpp b/renameengine/analyzewalk.cpp
new file mode 100644 (file)
index 0000000..751d8f5
--- /dev/null
@@ -0,0 +1,169 @@
+#include "analyzewalk.h"
+
+#include "renameengine.h"
+
+namespace RenameParser {
+
+AnalyzeWalk::AnalyzeWalk(QSharedPointer<AST::Node> ast) : AbstractWalk(ast)
+{
+
+}
+
+QString AnalyzeWalk::walk(Environment &env)
+{
+       using namespace AST;
+
+/*     switch (node->type())
+       {
+               case Node::Type_StatementList:
+               {
+                       QString result;
+                       foreach (QSharedPointer<Node> statement, node->children())
+                       {
+                               result = recursiveWalk(statement);
+                       }
+                       return result;
+               }
+               case Node::Type_Variable:
+               {
+                       Variable *v = (Variable *) node.data();
+                       if (variableUsage.contains(v->name()))
+                               variableUsage[v->name()] = 0;
+                       else
+                               ++variableUsage[v->name()];
+               }
+               break;
+               case Node::Type_Expression:
+               {
+                       Expression *e = (Expression *) node.data();
+                       switch (e->op())
+                       {
+                               case Op::Concat:
+                                       return recursiveWalk(e->child(0)) + recursiveWalk(e->child(1));
+
+                               case Op::Equals:
+                                       return recursiveWalk(e->child(0)) == recursiveWalk(e->child(1)) ? "1" : "0";
+
+                               case Op::Assign:
+                               {
+                                       QString value = recursiveWalk(e->child(1));
+                                       if (e->child(0)->type() != Node::Type_Variable)
+                                               return value;
+
+                                       Variable *var = (Variable *) e->child(0).data();
+                                       setValue(var->name(), value);
+                                       return value;
+                               }
+                               case Op::Conditional:
+                               {
+                                       if (isTrue(e->child(0)))
+                                               return recursiveWalk(e->child(1));
+                                       return recursiveWalk(e->child(2));
+                               }
+                               default:
+                                       return "";
+                       }
+               }
+               break;
+               case Node::Type_StringLiteral:
+               {
+                       StringLiteral *s = (StringLiteral *) node.data();
+                       return s->value();
+               }
+               break;
+               case Node::Type_NumericLiteral:
+               {
+                       NumericLiteral *n = (NumericLiteral *) node.data();
+                       return n->value();
+               }
+               break;
+               case Node::Type_FunctionCall:
+               {
+                       FunctionCall *functionCall = (FunctionCall *) node.data();
+
+                       if (RenameEngine::isRegistered(functionCall->name()))
+                       {
+                               RenameFunction func = RenameEngine::function(functionCall->name());
+                               if (!func) return "";
+
+                               QStringList evaluatedArgs;
+                               foreach (QSharedPointer<Node> arg, functionCall->arguments()->children())
+                               {
+                                       evaluatedArgs << recursiveWalk(arg);
+                               }
+                               return func(evaluatedArgs);
+                       }
+                       if (functionExists(functionCall->name()))
+                       {
+                               if (callDepth > maxCallDepth)
+                               {
+                                       qWarning() << "Recursion limit of" << maxCallDepth << "reached";
+                                       return "";
+                               }
+
+
+                               QSharedPointer<FunctionDeclaration> func = userFunction[functionCall->name()];
+
+                               Environment functionEnv;
+
+                               if (functionCall->arguments()->childCount() < func->arguments()->childCount())
+                               {
+                                       qWarning() << "Not enough parameters to call " << func->name();
+                                       return "";
+                               }
+                               for (int i = 0; i < func->arguments()->childCount(); ++i)
+                               {
+                                       const QSharedPointer<Node> declarationArg = func->arguments()->child(i);
+
+                                       Q_ASSERT(declarationArg->type() == Node::Type_FunctionDeclarationArgument);
+                                       FunctionDeclarationArgument *functionDeclarationArg = (FunctionDeclarationArgument *) declarationArg.data();
+
+                                       functionEnv[functionDeclarationArg->name()] = recursiveWalk(functionCall->arguments()->child(i));
+                               }
+
+                               ++callDepth;
+                               stack.push(functionEnv);
+                               QString result = recursiveWalk(func->functionBody());
+                               stack.pop();
+                               --callDepth;
+                               return result;
+                       }
+                       qWarning("Undefined function");
+                       return "";
+               }
+               break;
+               case Node::Type_Alternative:
+               {
+                       Alternative *a = (Alternative *) node.data();
+
+
+                       foreach (QSharedPointer<Node> child, a->arguments()->children())
+                       {
+                               QString value = recursiveWalk(child);
+                               if (!value.isEmpty())
+                                       return value;
+                       }
+                       return "";
+               }
+               break;
+               case Node::Type_FunctionDeclaration:
+               {
+                       QSharedPointer<FunctionDeclaration> f = qSharedPointerCast<FunctionDeclaration>(node);
+                       registerFunction(f->name(), f);
+               }
+               break;
+               case Node::Type_FunctionBody:
+               {
+                       Q_ASSERT(node->childCount() < 2);
+                       if (node->childCount() == 0)
+                               return "";
+                       return recursiveWalk(node->child(0));
+               }
+               default:
+               break;
+       }
+*/
+       return "";
+}
+
+} // namespace RenameParser
diff --git a/renameengine/analyzewalk.h b/renameengine/analyzewalk.h
new file mode 100644 (file)
index 0000000..634e9b6
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef ANALYZEWALK_H
+#define ANALYZEWALK_H
+
+#include "abstractwalk.h"
+#include <QStringList>
+
+namespace RenameParser {
+
+class AnalyzeWalk : public AbstractWalk
+{
+public:
+       AnalyzeWalk(QSharedPointer<AST::Node> ast);
+
+       QString walk(Environment &env);
+
+private:
+       QMap<QString, int> variableUsage;
+       QStringList messages;
+};
+
+} // namespace RenameParser
+
+#endif // ANALYZEWALK_H
diff --git a/renameengine/ast.cpp b/renameengine/ast.cpp
new file mode 100644 (file)
index 0000000..c21f787
--- /dev/null
@@ -0,0 +1,237 @@
+#include "ast.h"
+
+namespace RenameParser {
+namespace AST
+{
+
+Node::Node() : m_type(Type_Node)
+{}
+
+Node::~Node()
+{}
+
+Node::Type Node::type() const
+{
+       return m_type;
+}
+
+QList<QSharedPointer<Node> > Node::children() const
+{
+       return m_children;
+}
+
+QSharedPointer<Node> Node::child(int i) const
+{
+       if (i < m_children.count())
+               return m_children[i];
+       return QSharedPointer<Node>();
+}
+
+int Node::childCount() const
+{
+       return m_children.count();
+}
+
+void Node::addChild(QSharedPointer<Node> child)
+{
+       if (!child.isNull())
+               m_children.append(child);
+}
+
+void Node::addChildren(QList<QSharedPointer<Node> > children)
+{
+       m_children += children;
+}
+
+void Node::debug(int lvl) const
+{
+       Q_UNUSED(lvl);
+}
+
+void Node::debugChildren(int lvl) const
+{
+       Q_UNUSED(lvl);
+}
+
+// ----------------------------------------------------------------------------------------------
+
+BlockStatement::BlockStatement()
+{
+       m_type = Type_BlockStatement;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+StatementList::StatementList()
+{
+       m_type = Type_StatementList;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+IfStatement::IfStatement()
+{
+       m_type = Type_IfStatement;
+}
+
+
+// ----------------------------------------------------------------------------------------------
+
+FunctionDeclaration::FunctionDeclaration(const QString &name, QSharedPointer<FunctionBody> functionBody, QSharedPointer<FunctionDeclarationArgumentList> arguments)
+{
+       m_type = Type_FunctionDeclaration;
+       m_name = name;
+       m_functionBody = functionBody;
+       m_arguments = arguments;
+}
+
+QString FunctionDeclaration::name() const
+{
+       return m_name;
+}
+
+QSharedPointer<FunctionDeclarationArgumentList> FunctionDeclaration::arguments() const
+{
+       return m_arguments;
+}
+
+QSharedPointer<FunctionBody> FunctionDeclaration::functionBody() const
+{
+       return m_functionBody;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+Expression::Expression(Operator op)
+{
+       m_type = Type_Expression;
+       m_op = op;
+}
+
+Operator Expression::op() const
+{
+       return m_op;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+Name::Name(const QString &value)
+{
+       m_type = Type_Name;
+       m_value = value;
+}
+
+QString Name::value() const
+{
+       return m_value;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+StringLiteral::StringLiteral(const QString &value)
+{
+       m_type = Type_StringLiteral;
+       m_value = value;
+}
+
+QString StringLiteral::value() const
+{
+       return m_value;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+
+NumericLiteral::NumericLiteral(const QString value)
+{
+       m_type = Type_NumericLiteral;
+       m_value = value;
+}
+
+QString NumericLiteral::value() const
+{
+       return m_value;
+}
+
+
+// ----------------------------------------------------------------------------------------------
+
+Variable::Variable(const QString &name)
+{
+       m_type = Type_Variable;
+       m_name = name;
+}
+
+QString Variable::name() const
+{
+       return m_name;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+FunctionCall::FunctionCall(const QString &name, QSharedPointer<FunctionArgumentList> arguments)
+{
+       m_type = Type_FunctionCall;
+       m_name = name;
+       m_arguments = arguments;
+}
+
+QString FunctionCall::name() const
+{
+       return m_name;
+}
+
+QSharedPointer<FunctionArgumentList> FunctionCall::arguments() const
+{
+       return m_arguments;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+FunctionBody::FunctionBody()
+{
+       m_type = Type_FunctionBody;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+FunctionArgumentList::FunctionArgumentList()
+{
+       m_type = Type_FunctionArgumentList;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+FunctionDeclarationArgumentList::FunctionDeclarationArgumentList()
+{
+       m_type = Type_FunctionDeclarationArgumentList;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+FunctionDeclarationArgument::FunctionDeclarationArgument(const QString &name)
+{
+       m_type = Type_FunctionDeclarationArgument;
+       m_name = name;
+}
+
+QString FunctionDeclarationArgument::name() const
+{
+       return m_name;
+}
+
+// ----------------------------------------------------------------------------------------------
+
+Alternative::Alternative(QSharedPointer<FunctionArgumentList> arguments)
+{
+       m_type = Type_Alternative;
+       m_arguments = arguments;
+}
+
+QSharedPointer<FunctionArgumentList> Alternative::arguments() const
+{
+       return m_arguments;
+}
+
+} // namespace AST
+} // namespace RenameParser
diff --git a/renameengine/ast.h b/renameengine/ast.h
new file mode 100644 (file)
index 0000000..38c67fc
--- /dev/null
@@ -0,0 +1,246 @@
+#ifndef AST_H
+#define AST_H
+
+#include <QString>
+#include <QSharedPointer>
+
+namespace RenameParser {
+namespace AST
+{
+
+class Node;
+// Statements
+class BlockStatement;
+class StatementList;
+
+class IfStatement;
+class FunctionDeclaration;
+
+// Expressions
+class Expression;
+class Variable;
+class FunctionCall;
+
+// Literals
+class Name;
+class StringLiteral;
+class NumericLiteral;
+
+// Other
+class FunctionBody;
+class FunctionArgumentList;
+class FunctionArgument;
+
+class FunctionDeclarationArgumentList;
+class FunctionDeclarationArgument;
+
+// Special
+class Alternative;
+
+namespace Op
+{
+       enum Operator {
+               Assign,
+               Concat,
+               Equals,
+               Conditional
+       };
+}
+
+using namespace Op;
+
+class Node
+{
+public:
+       enum Type {
+               Type_Node,
+
+               // Statements
+               Type_BlockStatement,
+               Type_StatementList,
+
+               Type_IfStatement,
+               Type_FunctionDeclaration,
+
+               // Expressions
+               Type_Expression,
+               Type_Variable,
+               Type_FunctionCall,
+
+               // Literals
+               Type_Name,
+               Type_StringLiteral,
+               Type_NumericLiteral,
+
+               // Other
+               Type_FunctionBody,
+               Type_FunctionArgumentList,
+
+               Type_FunctionDeclarationArgumentList,
+               Type_FunctionDeclarationArgument,
+
+               // Special
+               Type_Alternative,
+       };
+
+       Node();
+       virtual ~Node();
+
+       virtual Type type() const;
+
+       virtual QList<QSharedPointer<Node> > children() const;
+       virtual QSharedPointer<Node> child(int i) const;
+       virtual int childCount() const;
+
+       virtual void addChild(QSharedPointer<Node> child);
+       virtual void addChildren(QList<QSharedPointer<Node> > children);
+
+       virtual void debug(int lvl = 0) const;
+       virtual void debugChildren(int lvl = 0) const;
+
+protected:
+       Type m_type;
+       QList<QSharedPointer<Node> > m_children;
+};
+
+class BlockStatement : public Node
+{
+public:
+       BlockStatement();
+
+};
+
+class StatementList : public Node
+{
+public:
+       StatementList();
+
+};
+
+class IfStatement : public Node
+{
+public:
+       IfStatement();
+
+};
+
+class FunctionDeclaration : public Node
+{
+public:
+       FunctionDeclaration(const QString &name, QSharedPointer<FunctionBody> functionBody, QSharedPointer<FunctionDeclarationArgumentList> arguments);
+       QString name() const;
+       QSharedPointer<FunctionBody> functionBody() const;
+       QSharedPointer<FunctionDeclarationArgumentList> arguments() const;
+private:
+       QString m_name;
+       QSharedPointer<FunctionBody> m_functionBody;
+       QSharedPointer<FunctionDeclarationArgumentList> m_arguments;
+};
+
+
+class Expression : public Node
+{
+public:
+       Expression(Operator op);
+       Operator op() const;
+
+protected:
+       Operator m_op;
+};
+
+class Name : public Node
+{
+public:
+       Name(const QString &value);
+       QString value() const;
+
+protected:
+       QString m_value;
+};
+
+class StringLiteral : public Node
+{
+public:
+       StringLiteral(const QString &value);
+       QString value() const;
+
+protected:
+       QString m_value;
+};
+
+class NumericLiteral : public Node
+{
+public:
+       NumericLiteral(const QString value);
+       QString value() const;
+
+protected:
+       QString m_value;
+};
+
+class Variable : public Node
+{
+public:
+       Variable(const QString &name);
+
+       QString name() const;
+
+protected:
+       QString m_name;
+};
+
+class FunctionCall : public Node
+{
+public:
+       FunctionCall(const QString &name, QSharedPointer<FunctionArgumentList> arguments);
+
+       QString name() const;
+       QSharedPointer<FunctionArgumentList> arguments() const;
+protected:
+       QString m_name;
+       QSharedPointer<FunctionArgumentList> m_arguments;
+};
+
+class FunctionBody : public Node
+{
+public:
+       FunctionBody();
+};
+
+class FunctionArgumentList : public Node
+{
+public:
+       FunctionArgumentList();
+};
+
+class FunctionDeclarationArgumentList : public Node
+{
+public:
+       FunctionDeclarationArgumentList();
+};
+
+class FunctionDeclarationArgument : public Node
+{
+public:
+       FunctionDeclarationArgument(const QString &name);
+
+       QString name() const;
+
+protected:
+       QString m_name;
+};
+
+class Alternative : public Node
+{
+public:
+       Alternative(QSharedPointer<FunctionArgumentList> arguments);
+
+       QSharedPointer<FunctionArgumentList> arguments() const;
+protected:
+       QSharedPointer<FunctionArgumentList> m_arguments;
+};
+
+} // namespace AST
+} // namespace RenameParser
+
+#endif // AST_H
diff --git a/renameengine/debugwalk.cpp b/renameengine/debugwalk.cpp
new file mode 100644 (file)
index 0000000..e012076
--- /dev/null
@@ -0,0 +1,191 @@
+#include "debugwalk.h"
+
+#include <QDebug>
+
+namespace RenameParser {
+
+DebugWalk::DebugWalk(QSharedPointer<AST::Node> ast) : AbstractWalk(ast)
+{
+       init();
+       level = 0;
+}
+
+QString DebugWalk::walk(Environment &env)
+{
+       Q_UNUSED(env);
+
+       level = 0;
+       return recursiveWalk(ast);
+}
+
+QString DebugWalk::recursiveWalk(QSharedPointer<AST::Node> node)
+{
+       using namespace AST;
+
+       QString ret;
+
+       if (node.isNull())
+       {
+               return QByteArray(level, '\t') + "Node is null\n";
+       }
+       if (level > 100)
+       {
+               qDebug() << "LEVEL < 100";
+               return "LEVEL < 100";
+       }
+
+       ret += QByteArray(level, '\t') + typeName[node->type()];
+       switch (node->type())
+       {
+               case Node::Type_Variable:
+               {
+                       Variable *v = (Variable *) node.data();
+                       ret += " NAME = " + v->name();
+               }
+               break;
+               case Node::Type_Expression:
+               {
+                       Expression *e = (Expression *) node.data();
+                       ret += " OP = " + operatorName[e->op()];
+               }
+               break;
+               case Node::Type_StringLiteral:
+               {
+                       StringLiteral *s = (StringLiteral *) node.data();
+                       ret += " = \"" + s->value() + "\"";
+               }
+               break;
+               case Node::Type_NumericLiteral:
+               {
+                       NumericLiteral *n = (NumericLiteral *) node.data();
+                       ret += " = " + n->value();
+               }
+               break;
+               case Node::Type_FunctionCall:
+               {
+                       FunctionCall *f = (FunctionCall *) node.data();
+                       ret += " = " + f->name();
+                       if (f->arguments()->childCount())
+                       {
+                               ret += " Arguments(" + QString::number(f->arguments()->childCount()) + ") {\n";
+                               ++level;
+                               ret += recursiveWalk(f->arguments());
+                               --level;
+                               ret += QByteArray(level, '\t') + "}\n";
+                       }
+                       else
+                               ret += " Arguments(0) {}\n";
+               }
+               break;
+               case Node::Type_Alternative:
+               {
+                       Alternative *f = (Alternative *) node.data();
+                       if (f->arguments()->childCount())
+                       {
+                               ret += " Arguments(" + QString::number(f->arguments()->childCount()) + ") {\n";
+                               ++level;
+                               ret += recursiveWalk(f->arguments());
+                               --level;
+                               ret += QByteArray(level, '\t') + "}\n";
+                       }
+                       else
+                               ret += " Arguments(0) {}\n";
+               }
+               break;
+               case Node::Type_FunctionDeclaration:
+               {
+                       FunctionDeclaration *f = (FunctionDeclaration *) node.data();
+                       ret += " = " + f->name() + " {\n";
+                       ++level;
+
+                       if (f->arguments()->childCount())
+                       {
+                               ret += QByteArray(level, '\t') + "Arguments(" + QString::number(f->arguments()->childCount()) + ") {\n";
+                               ++level;
+                               ret += recursiveWalk(f->arguments());
+                               --level;
+                               ret += QByteArray(level, '\t') + "}\n";
+                       }
+                       else
+                               ret += QByteArray(level, '\t') + "Arguments(0) {}\n";
+
+                       ret += recursiveWalk(f->functionBody());
+                       --level;
+                       ret += QByteArray(level, '\t') + "}\n";
+               }
+               break;
+               case Node::Type_FunctionBody:
+               {
+                       
+               }
+               default:
+               break;
+       }
+
+       if (node->type() != Node::Type_FunctionCall && node->type() != Node::Type_FunctionDeclaration)
+       {
+               if (node->childCount())
+               {
+                       ret += " Children(" + QString::number(node->childCount()) + ") {\n";
+                       ++level;
+                       foreach (QSharedPointer<Node> child, node->children())
+                       {
+                               ret += recursiveWalk(child);
+                       }
+                       --level;
+                       ret += QByteArray(level, '\t') + "}\n";
+               }
+               else
+                       ret += " Children(0) {}\n";
+       }
+       return ret;
+}
+
+void DebugWalk::init()
+{
+       using namespace AST;
+
+       if (initialized)
+               return;
+
+       typeName[Node::Type_Node] = "Node";
+
+       // Statements
+       typeName[Node::Type_BlockStatement] = "BlockStatement";
+       typeName[Node::Type_StatementList] = "StatementList";
+
+       typeName[Node::Type_IfStatement] = "IfStatement";
+       typeName[Node::Type_FunctionDeclaration] = "FunctionDeclaration";
+
+       // Expressions
+       typeName[Node::Type_Expression] = "Expression";
+       typeName[Node::Type_Variable] = "Variable";
+       typeName[Node::Type_FunctionCall] = "FunctionCall";
+
+       // Literals
+       typeName[Node::Type_Name] = "Name";
+       typeName[Node::Type_StringLiteral] = "StringLiteral";
+       typeName[Node::Type_NumericLiteral] = "NumericLiteral";
+
+       // Other
+       typeName[Node::Type_FunctionBody] = "FunctionBody";
+       typeName[Node::Type_FunctionArgumentList] = "FunctionArgumentList";
+
+       typeName[Node::Type_FunctionDeclarationArgumentList] = "FunctionDeclarationArgumentList";
+       typeName[Node::Type_FunctionDeclarationArgument] = "FunctionDeclarationArgument";
+
+       typeName[Node::Type_Alternative] = "Alternative";
+
+       operatorName[Op::Assign] = "Assign";
+       operatorName[Op::Concat] = "Concat";
+       operatorName[Op::Equals] = "Equals";
+       operatorName[Op::Conditional] = "Conditional";
+
+       initialized = true;
+}
+
+bool DebugWalk::initialized = false;
+QMap<AST::Node::Type, QString> DebugWalk::typeName;
+QMap<AST::Op::Operator, QString> DebugWalk::operatorName;
+
+}
diff --git a/renameengine/debugwalk.h b/renameengine/debugwalk.h
new file mode 100644 (file)
index 0000000..1d75cba
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef DEBUGWALK_H
+#define DEBUGWALK_H
+
+#include "abstractwalk.h"
+
+namespace RenameParser {
+
+class DebugWalk : public AbstractWalk
+{
+public:
+       DebugWalk(QSharedPointer<AST::Node> ast);
+
+       QString walk(Environment &env);
+
+private:
+       QString recursiveWalk(QSharedPointer<AST::Node> node);
+
+       int level;
+
+       static void init();
+       static bool initialized;
+       static QMap<AST::Node::Type, QString> typeName;
+       static QMap<AST::Op::Operator, QString> operatorName;
+};
+
+} // namespace RenameParser
+
+#endif // DEBUGWALK_H
diff --git a/renameengine/evaluatewalk.cpp b/renameengine/evaluatewalk.cpp
new file mode 100644 (file)
index 0000000..176099e
--- /dev/null
@@ -0,0 +1,219 @@
+#include "evaluatewalk.h"
+
+#include "renameengine.h"
+
+#include <QDebug>
+
+namespace RenameParser {
+
+EvaluateWalk::EvaluateWalk(QSharedPointer<AST::Node> ast) : AbstractWalk(ast)
+{
+       maxCallDepth = 100;
+       callDepth = 0;
+}
+
+QString EvaluateWalk::walk(Environment &env)
+{
+       stack.push(env);
+       QString result = recursiveWalk(ast);
+       env = stack.pop();
+
+       Q_ASSERT(stack.count() == 0);
+       Q_ASSERT(callDepth == 0);
+
+       return result;
+}
+
+
+QString EvaluateWalk::recursiveWalk(QSharedPointer<AST::Node> node)
+{
+       using namespace AST;
+
+       switch (node->type())
+       {
+               case Node::Type_StatementList:
+               {
+                       QString result;
+                       foreach (QSharedPointer<Node> statement, node->children())
+                       {
+                               result = recursiveWalk(statement);
+                       }
+                       return result;
+               }
+               case Node::Type_Variable:
+               {
+                       Variable *v = (Variable *) node.data();
+                       return lookupValue(v->name());
+               }
+               break;
+               case Node::Type_Expression:
+               {
+                       Expression *e = (Expression *) node.data();
+                       switch (e->op())
+                       {
+                               case Op::Concat:
+                                       return recursiveWalk(e->child(0)) + recursiveWalk(e->child(1));
+
+                               case Op::Equals:
+                                       return recursiveWalk(e->child(0)) == recursiveWalk(e->child(1)) ? "1" : "0";
+
+                               case Op::Assign:
+                               {
+                                       QString value = recursiveWalk(e->child(1));
+                                       if (e->child(0)->type() != Node::Type_Variable)
+                                               return value;
+
+                                       Variable *var = (Variable *) e->child(0).data();
+                                       setValue(var->name(), value);
+                                       return value;
+                               }
+                               case Op::Conditional:
+                               {
+                                       if (isTrue(e->child(0)))
+                                               return recursiveWalk(e->child(1));
+                                       return recursiveWalk(e->child(2));
+                               }
+                               default:
+                                       return "";
+                       }
+               }
+               break;
+               case Node::Type_StringLiteral:
+               {
+                       StringLiteral *s = (StringLiteral *) node.data();
+                       return s->value();
+               }
+               break;
+               case Node::Type_NumericLiteral:
+               {
+                       NumericLiteral *n = (NumericLiteral *) node.data();
+                       return n->value();
+               }
+               break;
+               case Node::Type_FunctionCall:
+               {
+                       FunctionCall *functionCall = (FunctionCall *) node.data();
+
+                       if (RenameEngine::isRegistered(functionCall->name()))
+                       {
+                               RenameFunction func = RenameEngine::function(functionCall->name());
+                               if (!func) return "";
+
+                               QStringList evaluatedArgs;
+                               foreach (QSharedPointer<Node> arg, functionCall->arguments()->children())
+                               {
+                                       evaluatedArgs << recursiveWalk(arg);
+                               }
+                               return func(evaluatedArgs);
+                       }
+                       if (functionExists(functionCall->name()))
+                       {
+                               if (callDepth > maxCallDepth)
+                               {
+                                       qWarning() << "Recursion limit of" << maxCallDepth << "reached";
+                                       return "";
+                               }
+
+
+                               QSharedPointer<FunctionDeclaration> func = userFunction[functionCall->name()];
+
+                               Environment functionEnv;
+
+                               if (functionCall->arguments()->childCount() < func->arguments()->childCount())
+                               {
+                                       qWarning() << "Not enough parameters to call " << func->name();
+                                       return "";
+                               }
+                               for (int i = 0; i < func->arguments()->childCount(); ++i)
+                               {
+                                       const QSharedPointer<Node> declarationArg = func->arguments()->child(i);
+
+                                       Q_ASSERT(declarationArg->type() == Node::Type_FunctionDeclarationArgument);
+                                       FunctionDeclarationArgument *functionDeclarationArg = (FunctionDeclarationArgument *) declarationArg.data();
+
+                                       functionEnv[functionDeclarationArg->name()] = recursiveWalk(functionCall->arguments()->child(i));
+                               }
+
+                               ++callDepth;
+                               stack.push(functionEnv);
+                               QString result = recursiveWalk(func->functionBody());
+                               stack.pop();
+                               --callDepth;
+                               return result;
+                       }
+                       qWarning("Undefined function");
+                       return "";
+               }
+               break;
+               case Node::Type_Alternative:
+               {
+                       Alternative *a = (Alternative *) node.data();
+
+
+                       foreach (QSharedPointer<Node> child, a->arguments()->children())
+                       {
+                               QString value = recursiveWalk(child);
+                               if (!value.isEmpty())
+                                       return value;
+                       }
+                       return "";
+               }
+               break;
+               case Node::Type_FunctionDeclaration:
+               {
+                       QSharedPointer<FunctionDeclaration> f = qSharedPointerCast<FunctionDeclaration>(node);
+                       registerFunction(f->name(), f);
+               }
+               break;
+               case Node::Type_FunctionBody:
+               {
+                       Q_ASSERT(node->childCount() < 2);
+                       if (node->childCount() == 0)
+                               return "";
+                       return recursiveWalk(node->child(0));
+               }
+               default:
+               break;
+       }
+
+       return "";
+}
+
+QString EvaluateWalk::lookupValue(const QString &varName) const
+{
+//     int stackSize = stack.size();
+       int i = stack.count();
+
+       while (i)
+       {
+               --i;
+               if (stack[i].contains(varName))
+                       return stack[i].value(varName);
+       }
+       return "";
+}
+
+void EvaluateWalk::setValue(const QString &varName, const QString &value)
+{
+       stack.top()[varName] = value;
+}
+
+void EvaluateWalk::registerFunction(const QString &name, QSharedPointer<AST::FunctionDeclaration> declaration)
+{
+       if (userFunction.contains(name))
+               qWarning() << "Redefining function" << name << "!!";
+       userFunction[name] = declaration;
+}
+
+bool EvaluateWalk::functionExists(const QString &functionName) const
+{
+       return userFunction.contains(functionName);
+}
+
+bool EvaluateWalk::isTrue(QSharedPointer<AST::Node> node)
+{
+       QString v = recursiveWalk(node);
+       return !(v.isEmpty() || v == "0");
+}
+
+} // namespace RenameParser
diff --git a/renameengine/evaluatewalk.h b/renameengine/evaluatewalk.h
new file mode 100644 (file)
index 0000000..67a74ce
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef EVALUATEWALK_H
+#define EVALUATEWALK_H
+
+#include "abstractwalk.h"
+
+#include <QStack>
+
+namespace RenameParser {
+
+class EvaluateWalk : public AbstractWalk
+{
+public:
+       EvaluateWalk(QSharedPointer<AST::Node> ast);
+
+       QString walk(Environment &env);
+
+private:
+       QString recursiveWalk(QSharedPointer<AST::Node> node);
+
+       QString lookupValue(const QString &varName) const;
+       void setValue(const QString &varName, const QString &value);
+
+       bool functionExists(const QString &functionName) const;
+       void registerFunction(const QString &name, QSharedPointer<AST::FunctionDeclaration> declaration);
+
+       bool isTrue(QSharedPointer<AST::Node> node);
+
+       bool returned;
+
+       QMap<QString, QSharedPointer<AST::FunctionDeclaration> > userFunction;
+       QStack<Environment> stack;
+
+
+       int callDepth;
+       int maxCallDepth;
+};
+
+} // namespace RenameParser
+
+#endif // EVALUATEWALK_H
diff --git a/renameengine/functions.cpp b/renameengine/functions.cpp
new file mode 100644 (file)
index 0000000..9daa61e
--- /dev/null
@@ -0,0 +1,82 @@
+#include "functions.h"
+
+namespace RenameParser {
+namespace RenameFunctions {
+
+QString max(const QStringList &args)
+{
+       int maximum = 0;
+       bool unset = true;
+
+       bool ok;
+       int tmp;
+       foreach (const QString &num, args)
+       {
+               tmp = num.toInt(&ok);
+               if (ok)
+               {
+                       if (unset)
+                       {
+                               maximum = tmp;
+                               unset = false;
+                       }
+                       else if (tmp > maximum)
+                       {
+                               maximum = tmp;
+                       }
+               }
+       }
+       return QString::number(maximum);
+}
+
+QString len(const QStringList &args)
+{
+       if (args.isEmpty())
+               return "0";
+       return QString::number(args[0].length());
+}
+
+QString pad(const QStringList &args)
+{
+       switch (args.count())
+       {
+               case 3:
+               {
+                       bool ok;
+                       int pad = args[1].toInt(&ok);
+                       if (!ok || args[2].isEmpty())
+                               return args[0];
+
+                       return args[0].rightJustified(pad, args[2][0]);
+               }
+               default:
+                       return args[0];
+               break;
+       }
+}
+
+QString repl(const QStringList &args)
+{
+       if (args.count() != 3)
+               return "";
+       QString ret = args[0];
+       return ret.replace(QRegExp(args[1]), args[2]);
+}
+
+QString match(const QStringList &args)
+{
+       if (args.count() != 2)
+               return "";
+       return QRegExp(args[1]).indexIn(args[0]) != -1 ? "1" : "";
+}
+
+QString alt(const QStringList &args)
+{
+       for (int i = 0; i < args.count(); ++i)
+               if (!args[i].isEmpty())
+                       return args[i];
+       return "";
+}
+
+} // namespace RenameFunctions
+} // namespace
diff --git a/renameengine/functions.h b/renameengine/functions.h
new file mode 100644 (file)
index 0000000..0e801a4
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+#include <QString>
+#include <QStringList>
+
+namespace RenameParser {
+
+namespace RenameFunctions
+{
+       QString max(const QStringList &args);
+       QString len(const QStringList &args);
+       QString pad(const QStringList &args);
+       QString repl(const QStringList &args);
+       QString match(const QStringList &args);
+       QString alt(const QStringList &args);
+}
+
+} // namespace
+
+#endif // FUNCTIONS_H
diff --git a/renameengine/parser.pri b/renameengine/parser.pri
new file mode 100644 (file)
index 0000000..cff3165
--- /dev/null
@@ -0,0 +1,18 @@
+HEADERS += $$PWD/renameengine.h \
+    $$PWD/functions.h \
+    $$PWD/abstractparser.h \
+    $$PWD/ast.h \
+    $$PWD/debugwalk.h \
+    $$PWD/abstractwalk.h \
+       $$PWD/evaluatewalk.h \
+    parser/analyzewalk.h
+SOURCES += $$PWD/renameengine.cpp \
+    $$PWD/functions.cpp \
+    $$PWD/abstractparser.cpp \
+    $$PWD/ast.cpp \
+    $$PWD/debugwalk.cpp \
+    $$PWD/abstractwalk.cpp \
+       $$PWD/evaluatewalk.cpp \
+    parser/analyzewalk.cpp
+include(AniAdd/aniadd.pri)
+include(ECMAScript/ecmascript.pri)
diff --git a/renameengine/renameengine.cpp b/renameengine/renameengine.cpp
new file mode 100644 (file)
index 0000000..cbbe6ec
--- /dev/null
@@ -0,0 +1,120 @@
+#include "renameengine.h"
+
+#include <QDebug>
+
+#include "AniAdd/renameparser.h"
+#include "ECMAScript/parser.h"
+
+namespace RenameParser {
+
+RenameEngine::RenameEngine(ParserType parserType)
+{
+       staticInit();
+       m_parserType = parserType;
+       parser = createParser(parserType);
+}
+
+RenameEngine::~RenameEngine()
+{
+       delete parser;
+}
+
+RenameEngine::ParserType RenameEngine::currentParserType() const
+{
+       return m_parserType;
+}
+
+void RenameEngine::setCurrentParserType(ParserType parserType)
+{
+       m_parserType = parserType;
+       delete parser;
+       parser = createParser(parserType);
+}
+
+QString RenameEngine::renameString() const
+{
+       return parser->renameString();
+}
+
+bool RenameEngine::parse(const QString &string)
+{
+       bool b = parser->parse(string);
+#ifdef PARSER_DEBUG
+qDebug() << "-----------------------------------------------------------------";
+#endif
+return b;
+}
+
+QString RenameEngine::evaluate(Environment &env)
+{
+       return parser->evaluate(env);
+}
+
+QString RenameEngine::error() const
+{
+       return parser->error();
+}
+
+int RenameEngine::line() const
+{
+       return parser->line();
+}
+
+int RenameEngine::column() const
+{
+       return parser->column();
+}
+
+AbstractParser *RenameEngine::createParser(ParserType type) const
+{
+       switch (type)
+       {
+               case ECMAScript:
+                       return new ECMAScript::Parser;
+               break;
+               case AniAdd:
+               default:
+                       return new AniAdd::RenameParser;
+               break;
+       }
+}
+
+void RenameEngine::staticInit()
+{
+       if (staticInitialised)
+               return;
+
+       registerFunction("max", RenameFunctions::max);
+       registerFunction("pad", RenameFunctions::pad);
+       registerFunction("len", RenameFunctions::len);
+       registerFunction("repl", RenameFunctions::repl);
+       registerFunction("match", RenameFunctions::match);
+       registerFunction("alt", RenameFunctions::alt);
+
+       staticInitialised = true;
+}
+
+void RenameEngine::registerFunction(const QString &name, RenameFunction func)
+{
+       functions[name] = func;
+}
+
+RenameFunction RenameEngine::function(const QString &name)
+{
+       return functions.value(name, 0);
+}
+
+bool RenameEngine::isRegistered(const QString &name)
+{
+       return functions.contains(name);
+}
+
+QStringList RenameEngine::registeredFunctions()
+{
+       return functions.keys();
+}
+
+QMap<QString, RenameFunction> RenameEngine::functions;
+bool RenameEngine::staticInitialised = false;
+
+} // namespace
diff --git a/renameengine/renameengine.h b/renameengine/renameengine.h
new file mode 100644 (file)
index 0000000..ded6db5
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef RENAMEENGINE_H
+#define RENAMEENGINE_H
+
+#include <QString>
+#include <QMap>
+
+#include "abstractparser.h"
+#include "functions.h"
+
+namespace RenameParser {
+
+typedef QString (*RenameFunction)(const QStringList &args);
+
+class RenameEngine
+{
+public:
+       enum ParserType {
+               AniAdd,
+               ECMAScript,
+               EndParser
+       };
+
+       RenameEngine(ParserType parserType = AniAdd);
+       ~RenameEngine();
+
+       ParserType currentParserType() const;
+       void setCurrentParserType(ParserType parserType);
+
+       QString renameString() const;
+       bool parse(const QString &string);
+
+       QString evaluate(Environment &env);
+
+       QString error() const;
+       int line() const;
+       int column() const;
+
+private:
+       AbstractParser *createParser(ParserType type) const;
+
+       ParserType m_parserType;
+       AbstractParser *parser;
+
+       QString m_renameString;
+
+public:
+       static void registerFunction(const QString &name, RenameFunction func);
+       static RenameFunction function(const QString &name);
+       static bool isRegistered(const QString &name);
+       static QStringList registeredFunctions();
+
+private:
+       static void staticInit();
+       static QMap<QString, RenameFunction> functions;
+       static bool staticInitialised;
+};
+
+} // namespace
+
+#endif // RENAMEENGINE_H