From ebbc69505f5afe28058277d7480d7d005b566bc7 Mon Sep 17 00:00:00 2001 From: APTX Date: Sat, 11 Dec 2010 18:02:19 +0100 Subject: [PATCH] Add RenameParser --- anidbudpclient.pro | 40 +- renameengine/AniAdd/aniadd.pri | 6 + renameengine/AniAdd/lexer.cpp | 135 +++++ renameengine/AniAdd/lexer.h | 52 ++ renameengine/AniAdd/parser.g | 780 +++++++++++++++++++++++++ renameengine/AniAdd/renamegrammar.cpp | 200 +++++++ renameengine/AniAdd/renamegrammar_p.h | 83 +++ renameengine/AniAdd/renameparser.cpp | 642 ++++++++++++++++++++ renameengine/AniAdd/renameparser.h | 63 ++ renameengine/ECMAScript/ecmascript.pri | 3 + renameengine/ECMAScript/parser.cpp | 98 ++++ renameengine/ECMAScript/parser.h | 35 ++ renameengine/abstractparser.cpp | 28 + renameengine/abstractparser.h | 32 + renameengine/abstractwalk.cpp | 15 + renameengine/abstractwalk.h | 24 + renameengine/analyzewalk.cpp | 169 ++++++ renameengine/analyzewalk.h | 23 + renameengine/ast.cpp | 237 ++++++++ renameengine/ast.h | 246 ++++++++ renameengine/debugwalk.cpp | 191 ++++++ renameengine/debugwalk.h | 28 + renameengine/evaluatewalk.cpp | 219 +++++++ renameengine/evaluatewalk.h | 40 ++ renameengine/functions.cpp | 82 +++ renameengine/functions.h | 21 + renameengine/parser.pri | 18 + renameengine/renameengine.cpp | 120 ++++ renameengine/renameengine.h | 60 ++ 29 files changed, 3688 insertions(+), 2 deletions(-) create mode 100644 renameengine/AniAdd/aniadd.pri create mode 100644 renameengine/AniAdd/lexer.cpp create mode 100644 renameengine/AniAdd/lexer.h create mode 100644 renameengine/AniAdd/parser.g create mode 100644 renameengine/AniAdd/renamegrammar.cpp create mode 100644 renameengine/AniAdd/renamegrammar_p.h create mode 100644 renameengine/AniAdd/renameparser.cpp create mode 100644 renameengine/AniAdd/renameparser.h create mode 100644 renameengine/ECMAScript/ecmascript.pri create mode 100644 renameengine/ECMAScript/parser.cpp create mode 100644 renameengine/ECMAScript/parser.h create mode 100644 renameengine/abstractparser.cpp create mode 100644 renameengine/abstractparser.h create mode 100644 renameengine/abstractwalk.cpp create mode 100644 renameengine/abstractwalk.h create mode 100644 renameengine/analyzewalk.cpp create mode 100644 renameengine/analyzewalk.h create mode 100644 renameengine/ast.cpp create mode 100644 renameengine/ast.h create mode 100644 renameengine/debugwalk.cpp create mode 100644 renameengine/debugwalk.h create mode 100644 renameengine/evaluatewalk.cpp create mode 100644 renameengine/evaluatewalk.h create mode 100644 renameengine/functions.cpp create mode 100644 renameengine/functions.h create mode 100644 renameengine/parser.pri create mode 100644 renameengine/renameengine.cpp create mode 100644 renameengine/renameengine.h diff --git a/anidbudpclient.pro b/anidbudpclient.pro index 5f01f7e..cf66359 100644 --- a/anidbudpclient.pro +++ b/anidbudpclient.pro @@ -32,7 +32,7 @@ SOURCES += client.cpp \ hashproducer.cpp \ hashconsumer.cpp \ clientsentcommandsmodel.cpp \ - clientqueuedcommandsmodel.cpp + clientqueuedcommandsmodel.cpp HEADERS += client.h \ anidbudpclient_global.h \ @@ -51,7 +51,7 @@ HEADERS += client.h \ hashconsumer.h \ circularbuffer.h \ clientsentcommandsmodel.h \ - clientqueuedcommandsmodel.h + clientqueuedcommandsmodel.h CONV_HEADERS += include/AniDBUdpClient/Client \ include/AniDBUdpClient/AbstractCommand \ @@ -65,3 +65,39 @@ CONV_HEADERS += include/AniDBUdpClient/Client \ include/AniDBUdpClient/Hash \ include/AniDBUdpClient/ClientSentCommandsModel \ include/AniDBUdpClient/ClientQueuedCommandsModel + +# RenameParser Files + +SOURCES += + renameengine/renameengine.cpp \ + renameengine/functions.cpp \ + renameengine/evaluatewalk.cpp \ + renameengine/debugwalk.cpp \ + renameengine/ast.cpp \ + renameengine/analyzewalk.cpp \ + renameengine/abstractwalk.cpp \ + renameengine/abstractparser.cpp \ + renameengine/AniAdd/renameparser.cpp \ + renameengine/AniAdd/renamegrammar.cpp \ + renameengine/AniAdd/lexer.cpp \ + renameengine/ECMAScript/parser.cpp + +SOURCES += + renameengine/renameengine.h \ + renameengine/functions.h \ + renameengine/evaluatewalk.h \ + renameengine/debugwalk.h \ + renameengine/ast.h \ + renameengine/analyzewalk.h \ + renameengine/abstractwalk.h \ + renameengine/abstractparser.h \ + renameengine/AniAdd/renameparser.h \ + renameengine/AniAdd/renamegrammar_p.h \ + renameengine/AniAdd/lexer.h \ + renameengine/ECMAScript/parser.h + +OTHER_FILES += \ + renameengine/parser.pri \ + renameengine/AniAdd/parser.g \ + renameengine/AniAdd/aniadd.pri \ + renameengine/ECMAScript/ecmascript.pri diff --git a/renameengine/AniAdd/aniadd.pri b/renameengine/AniAdd/aniadd.pri new file mode 100644 index 0000000..47a92cd --- /dev/null +++ b/renameengine/AniAdd/aniadd.pri @@ -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 index 0000000..ca6c1cd --- /dev/null +++ b/renameengine/AniAdd/lexer.cpp @@ -0,0 +1,135 @@ +#include "lexer.h" + +#include + +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 Lexer::tokenMap; +bool Lexer::staticInitialised = false; + +}} // namespace diff --git a/renameengine/AniAdd/lexer.h b/renameengine/AniAdd/lexer.h new file mode 100644 index 0000000..cdc44bd --- /dev/null +++ b/renameengine/AniAdd/lexer.h @@ -0,0 +1,52 @@ +#ifndef LEXER_H +#define LEXER_H + +#include +#include + +#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 tokenMap; +}; + +}} // namespace + +#endif // LEXER_H diff --git a/renameengine/AniAdd/parser.g b/renameengine/AniAdd/parser.g new file mode 100644 index 0000000..e166607 --- /dev/null +++ b/renameengine/AniAdd/parser.g @@ -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 + +#include + +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 &sym(int index) + { return m_symStack[m_tos + index - 1]; } + + int m_tos; + QVector m_stateStack; + QVector > m_symStack; + int m_line; + int m_column; + QString m_error; + QString m_result; + + Lexer *lexer; + QSharedPointer ast; +}; + +}} // namespace + +#endif // ANIADDPARSER_H + +:/ + +/. +#include +#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(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(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(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 arglist(new FunctionDeclarationArgumentList); + + Q_ASSERT(sym(5)->type() == Node::Type_FunctionBody); + QSharedPointer functionBody = qSharedPointerCast(sym(5)); + + FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist); + sym(1) = QSharedPointer(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 arglist = qSharedPointerCast(sym(3)); + + Q_ASSERT(sym(6)->type() == Node::Type_FunctionBody); + QSharedPointer functionBody = qSharedPointerCast(sym(6)); + + FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist); + sym(1) = QSharedPointer(functionDeclaration); + } break; +./ + +FunctionBody: ExpressionStatement ; +/. +case $rule_number: { +#ifdef PARSER_DEBUG +qDebug() << "FunctionBody: ExpressionStatement ;"; +#endif + + QSharedPointer functionBody(new FunctionBody); + functionBody->addChild(sym(1)); + sym(1) = functionBody; +} break; +./ + +FunctionBody: CompoundStatement ; +/. +case $rule_number: { +#ifdef PARSER_DEBUG +qDebug() << "FunctionBody: CompoundStatement ;"; +#endif + + QSharedPointer 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(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(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(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(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(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(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(string); +} break; +./ + +PrimaryExpression: NUMBER ; +/. +case $rule_number: { +#ifdef PARSER_DEBUG +qDebug() << "PrimaryExpression: NUMBER ;"; +#endif + NumericLiteral *number = new NumericLiteral(lexer->value()); + sym(1) = QSharedPointer(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 arglist = qSharedPointerCast(sym(2)); + + Alternative *alt = new Alternative(arglist); + sym(1) = QSharedPointer(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 arglist(new FunctionArgumentList()); + FunctionCall *call = new FunctionCall(name->value(), arglist); + sym(1) = QSharedPointer(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 arglist = qSharedPointerCast(sym(4)); + + FunctionCall *call = new FunctionCall(name->value(), arglist); + sym(1) = QSharedPointer(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(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(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(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(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(arg); +} break; +./ + +Name: IDENTIFIER ; +/. +case $rule_number: { +#ifdef PARSER_DEBUG +qDebug() << "Name: IDENTIFIER ;"; +#endif + Name *name = new Name(lexer->value()); + sym(1) = QSharedPointer(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 index 0000000..f70de6c --- /dev/null +++ b/renameengine/AniAdd/renamegrammar.cpp @@ -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 index 0000000..e5193cd --- /dev/null +++ b/renameengine/AniAdd/renamegrammar_p.h @@ -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 index 0000000..e1b1c0d --- /dev/null +++ b/renameengine/AniAdd/renameparser.cpp @@ -0,0 +1,642 @@ +// This file was generated by qlalr - DO NOT EDIT! + +#line 94 "parser.g" + +#include +#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(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(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(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 arglist(new FunctionDeclarationArgumentList); + + Q_ASSERT(sym(5)->type() == Node::Type_FunctionBody); + QSharedPointer functionBody = qSharedPointerCast(sym(5)); + + FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist); + sym(1) = QSharedPointer(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 arglist = qSharedPointerCast(sym(3)); + + Q_ASSERT(sym(6)->type() == Node::Type_FunctionBody); + QSharedPointer functionBody = qSharedPointerCast(sym(6)); + + FunctionDeclaration *functionDeclaration = new FunctionDeclaration(name->value(), functionBody, arglist); + sym(1) = QSharedPointer(functionDeclaration); + } break; + +#line 360 "parser.g" + +case 12: { +#ifdef PARSER_DEBUG +qDebug() << "FunctionBody: ExpressionStatement ;"; +#endif + + QSharedPointer 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 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(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(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(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(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(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(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(string); +} break; + +#line 539 "parser.g" + +case 28: { +#ifdef PARSER_DEBUG +qDebug() << "PrimaryExpression: NUMBER ;"; +#endif + NumericLiteral *number = new NumericLiteral(lexer->value()); + sym(1) = QSharedPointer(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 arglist = qSharedPointerCast(sym(2)); + + Alternative *alt = new Alternative(arglist); + sym(1) = QSharedPointer(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 arglist(new FunctionArgumentList()); + FunctionCall *call = new FunctionCall(name->value(), arglist); + sym(1) = QSharedPointer(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 arglist = qSharedPointerCast(sym(4)); + + FunctionCall *call = new FunctionCall(name->value(), arglist); + sym(1) = QSharedPointer(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(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(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(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(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(arg); +} break; + +#line 707 "parser.g" + +case 40: { +#ifdef PARSER_DEBUG +qDebug() << "Name: IDENTIFIER ;"; +#endif + Name *name = new Name(lexer->value()); + sym(1) = QSharedPointer(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 index 0000000..e8327cd --- /dev/null +++ b/renameengine/AniAdd/renameparser.h @@ -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 + +#include + +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 &sym(int index) + { return m_symStack[m_tos + index - 1]; } + + int m_tos; + QVector m_stateStack; + QVector > m_symStack; + int m_line; + int m_column; + QString m_error; + QString m_result; + + Lexer *lexer; + QSharedPointer ast; +}; + +}} // namespace + +#endif // ANIADDPARSER_H + diff --git a/renameengine/ECMAScript/ecmascript.pri b/renameengine/ECMAScript/ecmascript.pri new file mode 100644 index 0000000..f604134 --- /dev/null +++ b/renameengine/ECMAScript/ecmascript.pri @@ -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 index 0000000..9ab685b --- /dev/null +++ b/renameengine/ECMAScript/parser.cpp @@ -0,0 +1,98 @@ +#include "parser.h" + +#include + +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 index 0000000..10d0580 --- /dev/null +++ b/renameengine/ECMAScript/parser.h @@ -0,0 +1,35 @@ +#ifndef ECMASCRIPTPARSER_H +#define ECMASCRIPTPARSER_H + +#include +#include +#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 index 0000000..97cd47a --- /dev/null +++ b/renameengine/abstractparser.cpp @@ -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 index 0000000..dc30190 --- /dev/null +++ b/renameengine/abstractparser.h @@ -0,0 +1,32 @@ +#ifndef ABSTRACTPARSER_H +#define ABSTRACTPARSER_H + +#include +#include + +namespace RenameParser { + +typedef QMap 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 index 0000000..e65550c --- /dev/null +++ b/renameengine/abstractwalk.cpp @@ -0,0 +1,15 @@ +#include "abstractwalk.h" + +namespace RenameParser { + +AbstractWalk::AbstractWalk(QSharedPointer 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 index 0000000..3c06b50 --- /dev/null +++ b/renameengine/abstractwalk.h @@ -0,0 +1,24 @@ +#ifndef ABSTRACTWALK_H +#define ABSTRACTWALK_H + +#include "ast.h" +#include +#include + +namespace RenameParser { + +typedef QMap Environment; + +class AbstractWalk +{ +public: + AbstractWalk(QSharedPointer ast); + + virtual QString walk(Environment &env); + + QSharedPointer ast; +}; + +} // namespace RenameParser + +#endif // ABSTRACTWALK_H diff --git a/renameengine/analyzewalk.cpp b/renameengine/analyzewalk.cpp new file mode 100644 index 0000000..751d8f5 --- /dev/null +++ b/renameengine/analyzewalk.cpp @@ -0,0 +1,169 @@ +#include "analyzewalk.h" + +#include "renameengine.h" + +namespace RenameParser { + +AnalyzeWalk::AnalyzeWalk(QSharedPointer ast) : AbstractWalk(ast) +{ + +} + +QString AnalyzeWalk::walk(Environment &env) +{ + using namespace AST; + +/* switch (node->type()) + { + case Node::Type_StatementList: + { + QString result; + foreach (QSharedPointer 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 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 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 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 child, a->arguments()->children()) + { + QString value = recursiveWalk(child); + if (!value.isEmpty()) + return value; + } + return ""; + } + break; + case Node::Type_FunctionDeclaration: + { + QSharedPointer f = qSharedPointerCast(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 index 0000000..634e9b6 --- /dev/null +++ b/renameengine/analyzewalk.h @@ -0,0 +1,23 @@ +#ifndef ANALYZEWALK_H +#define ANALYZEWALK_H + +#include "abstractwalk.h" +#include + +namespace RenameParser { + +class AnalyzeWalk : public AbstractWalk +{ +public: + AnalyzeWalk(QSharedPointer ast); + + QString walk(Environment &env); + +private: + QMap variableUsage; + QStringList messages; +}; + +} // namespace RenameParser + +#endif // ANALYZEWALK_H diff --git a/renameengine/ast.cpp b/renameengine/ast.cpp new file mode 100644 index 0000000..c21f787 --- /dev/null +++ b/renameengine/ast.cpp @@ -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 > Node::children() const +{ + return m_children; +} + +QSharedPointer Node::child(int i) const +{ + if (i < m_children.count()) + return m_children[i]; + return QSharedPointer(); +} + +int Node::childCount() const +{ + return m_children.count(); +} + +void Node::addChild(QSharedPointer child) +{ + if (!child.isNull()) + m_children.append(child); +} + +void Node::addChildren(QList > 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, QSharedPointer arguments) +{ + m_type = Type_FunctionDeclaration; + m_name = name; + m_functionBody = functionBody; + m_arguments = arguments; +} + +QString FunctionDeclaration::name() const +{ + return m_name; +} + +QSharedPointer FunctionDeclaration::arguments() const +{ + return m_arguments; +} + +QSharedPointer 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 arguments) +{ + m_type = Type_FunctionCall; + m_name = name; + m_arguments = arguments; +} + +QString FunctionCall::name() const +{ + return m_name; +} + +QSharedPointer 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 arguments) +{ + m_type = Type_Alternative; + m_arguments = arguments; +} + +QSharedPointer Alternative::arguments() const +{ + return m_arguments; +} + +} // namespace AST +} // namespace RenameParser diff --git a/renameengine/ast.h b/renameengine/ast.h new file mode 100644 index 0000000..38c67fc --- /dev/null +++ b/renameengine/ast.h @@ -0,0 +1,246 @@ +#ifndef AST_H +#define AST_H + +#include +#include + +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 > children() const; + virtual QSharedPointer child(int i) const; + virtual int childCount() const; + + virtual void addChild(QSharedPointer child); + virtual void addChildren(QList > children); + + virtual void debug(int lvl = 0) const; + virtual void debugChildren(int lvl = 0) const; + +protected: + Type m_type; + QList > 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, QSharedPointer arguments); + QString name() const; + QSharedPointer functionBody() const; + QSharedPointer arguments() const; +private: + QString m_name; + QSharedPointer m_functionBody; + QSharedPointer 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 arguments); + + QString name() const; + QSharedPointer arguments() const; +protected: + QString m_name; + QSharedPointer 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 arguments); + + QSharedPointer arguments() const; +protected: + QSharedPointer m_arguments; +}; + +} // namespace AST +} // namespace RenameParser + +#endif // AST_H diff --git a/renameengine/debugwalk.cpp b/renameengine/debugwalk.cpp new file mode 100644 index 0000000..e012076 --- /dev/null +++ b/renameengine/debugwalk.cpp @@ -0,0 +1,191 @@ +#include "debugwalk.h" + +#include + +namespace RenameParser { + +DebugWalk::DebugWalk(QSharedPointer ast) : AbstractWalk(ast) +{ + init(); + level = 0; +} + +QString DebugWalk::walk(Environment &env) +{ + Q_UNUSED(env); + + level = 0; + return recursiveWalk(ast); +} + +QString DebugWalk::recursiveWalk(QSharedPointer 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 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 DebugWalk::typeName; +QMap DebugWalk::operatorName; + +} diff --git a/renameengine/debugwalk.h b/renameengine/debugwalk.h new file mode 100644 index 0000000..1d75cba --- /dev/null +++ b/renameengine/debugwalk.h @@ -0,0 +1,28 @@ +#ifndef DEBUGWALK_H +#define DEBUGWALK_H + +#include "abstractwalk.h" + +namespace RenameParser { + +class DebugWalk : public AbstractWalk +{ +public: + DebugWalk(QSharedPointer ast); + + QString walk(Environment &env); + +private: + QString recursiveWalk(QSharedPointer node); + + int level; + + static void init(); + static bool initialized; + static QMap typeName; + static QMap operatorName; +}; + +} // namespace RenameParser + +#endif // DEBUGWALK_H diff --git a/renameengine/evaluatewalk.cpp b/renameengine/evaluatewalk.cpp new file mode 100644 index 0000000..176099e --- /dev/null +++ b/renameengine/evaluatewalk.cpp @@ -0,0 +1,219 @@ +#include "evaluatewalk.h" + +#include "renameengine.h" + +#include + +namespace RenameParser { + +EvaluateWalk::EvaluateWalk(QSharedPointer 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 node) +{ + using namespace AST; + + switch (node->type()) + { + case Node::Type_StatementList: + { + QString result; + foreach (QSharedPointer 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 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 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 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 child, a->arguments()->children()) + { + QString value = recursiveWalk(child); + if (!value.isEmpty()) + return value; + } + return ""; + } + break; + case Node::Type_FunctionDeclaration: + { + QSharedPointer f = qSharedPointerCast(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 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 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 index 0000000..67a74ce --- /dev/null +++ b/renameengine/evaluatewalk.h @@ -0,0 +1,40 @@ +#ifndef EVALUATEWALK_H +#define EVALUATEWALK_H + +#include "abstractwalk.h" + +#include + +namespace RenameParser { + +class EvaluateWalk : public AbstractWalk +{ +public: + EvaluateWalk(QSharedPointer ast); + + QString walk(Environment &env); + +private: + QString recursiveWalk(QSharedPointer 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 declaration); + + bool isTrue(QSharedPointer node); + + bool returned; + + QMap > userFunction; + QStack stack; + + + int callDepth; + int maxCallDepth; +}; + +} // namespace RenameParser + +#endif // EVALUATEWALK_H diff --git a/renameengine/functions.cpp b/renameengine/functions.cpp new file mode 100644 index 0000000..9daa61e --- /dev/null +++ b/renameengine/functions.cpp @@ -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 index 0000000..0e801a4 --- /dev/null +++ b/renameengine/functions.h @@ -0,0 +1,21 @@ +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +#include +#include + +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 index 0000000..cff3165 --- /dev/null +++ b/renameengine/parser.pri @@ -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 index 0000000..cbbe6ec --- /dev/null +++ b/renameengine/renameengine.cpp @@ -0,0 +1,120 @@ +#include "renameengine.h" + +#include + +#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 RenameEngine::functions; +bool RenameEngine::staticInitialised = false; + +} // namespace diff --git a/renameengine/renameengine.h b/renameengine/renameengine.h new file mode 100644 index 0000000..ded6db5 --- /dev/null +++ b/renameengine/renameengine.h @@ -0,0 +1,60 @@ +#ifndef RENAMEENGINE_H +#define RENAMEENGINE_H + +#include +#include + +#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 functions; + static bool staticInitialised; +}; + +} // namespace + +#endif // RENAMEENGINE_H -- 2.52.0