hashproducer.cpp \\r
hashconsumer.cpp \\r
clientsentcommandsmodel.cpp \\r
- clientqueuedcommandsmodel.cpp\r
+ clientqueuedcommandsmodel.cpp\r
\r
HEADERS += client.h \\r
anidbudpclient_global.h \\r
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
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
--- /dev/null
+HEADERS += $$PWD/renameparser.h \
+ $$PWD/renamegrammar_p.h \
+ $$PWD/lexer.h
+SOURCES += $$PWD/renameparser.cpp \
+ $$PWD/renamegrammar.cpp \
+ $$PWD/lexer.cpp \
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+%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
+
+./
--- /dev/null
+// 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};
+
--- /dev/null
+// 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
+
--- /dev/null
+// 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
+
--- /dev/null
+// 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
+
--- /dev/null
+QT *= script
+HEADERS += $$PWD/parser.h
+SOURCES += $$PWD/parser.cpp
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#include "abstractwalk.h"
+
+namespace RenameParser {
+
+AbstractWalk::AbstractWalk(QSharedPointer<AST::Node> ast)
+{
+ this->ast = ast;
+}
+
+QString AbstractWalk::walk(Environment &)
+{
+ return "";
+}
+
+} // namespace RenameParser
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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;
+
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+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)
--- /dev/null
+#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
--- /dev/null
+#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