Mon, 26 Jan 2015 12:46:58 +0200
- more work on scripting
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/main.cc | file | annotate | diff | comparison | revisions | |
src/script/parser.cpp | file | annotate | diff | comparison | revisions | |
src/script/parser.h | file | annotate | diff | comparison | revisions |
--- a/CMakeLists.txt Mon Jan 26 01:16:56 2015 +0200 +++ b/CMakeLists.txt Mon Jan 26 12:46:58 2015 +0200 @@ -71,6 +71,7 @@ src/editmodes/magicWandMode.cc src/editmodes/rectangleMode.cc src/editmodes/selectMode.cc + src/script/parser.cpp ) set (LDFORGE_HEADERS
--- a/src/main.cc Mon Jan 26 01:16:56 2015 +0200 +++ b/src/main.cc Mon Jan 26 12:46:58 2015 +0200 @@ -33,6 +33,7 @@ #include "configDialog.h" #include "dialogs.h" #include "crashCatcher.h" +#include "script/parser.h" MainWindow* g_win = null; static QString g_versionString, g_fullVersionString; @@ -47,6 +48,13 @@ // int main (int argc, char* argv[]) { + QFile fp ("script.txt", QIODevice::ReadOnly); + Script::Parser parser (QString::fromLocal8Bit (fp.readAll())); + parser.parse(); + QFile fp2 ("script.out.txt", QIODevice::WriteOnly); + fp2.write (parser.preprocessedScript(), parser.preprocessedScript().length()); + return 0; + QApplication app (argc, argv); app.setOrganizationName (APPNAME); app.setApplicationName (APPNAME);
--- a/src/script/parser.cpp Mon Jan 26 01:16:56 2015 +0200 +++ b/src/script/parser.cpp Mon Jan 26 12:46:58 2015 +0200 @@ -1,16 +1,132 @@ #include "parser.h" +static const char* TokenNames[] = +{ + "==", + "<=", + ">=", + "&&", + "||", + "$", + ":", + ";", + ".", + ",", + "=", + "<", + ">", + "?", + "{", + "}", + "[", + "]", + "(", + ")", + "-", + "+", + "*", + "/", + "\\", + "&", + "^", + "|", + "!", + "@", + "#", + "~", + "`", + "%", + "<string>", + "<symbol>", + "<number>", + "<any>", +}; + Script::Parser::Parser(QString text) : - m_data (text) {} + m_script(text) {} void Script::Parser::parse() { + bool inString = false; + bool inComment = false; + bool inBackslash = false; + int ln = 1; + int pos = 0; + + // Preprocess + for (QChar qch : text) + { + char ch = qch.toAscii(); + + if (not inComment && not inString && ch == '\0') + scriptError ("bad character %s in script text on line %d", qch, ln); + + if (ch == '\\') + { + inBackslash = true; + continue; + } + + if (inBackslash) + { + if (inString) + { + switch (ch) + { + case 'n': data << '\n'; break; + case 't': data << '\t'; break; + case 'b': data << '\b'; break; + case '\\': data << '\\'; break; + default: scriptError ("misplaced backslash on line %d", ln); + } + + ++pos; + inBackslash == false; + continue; + } + else if (ch != '\n') + { + scriptError ("misplaced backslash on line %d", ln); + } + } + + if (ch == '\n') + { + if (inString) + scriptError ("unterminated string on line %d", ln); + + if (not inBackslash) + { + m_data << ';'; + ++pos; + inComment = false; + m_lineEndings << pos; + ++ln; + } + else + { + inBackslash = false; + } + continue; + } + + if (ch == '#' && not inString) + { + inComment = true; + continue; + } + + m_data << ch; + ++pos; + } + m_position.reset(); } bool Script::Parser::next(TokenType desiredType) { SavedPosition oldpos = position(); + return false; } void Script::Parser::mustGetNext(TokenType desiredType) @@ -20,10 +136,9 @@ bool Script::Parser::peekNext(Token& tok) { - + return false; } - const Script::SavedPosition& Script::Parser::position() const { return m_position;
--- a/src/script/parser.h Mon Jan 26 01:16:56 2015 +0200 +++ b/src/script/parser.h Mon Jan 26 12:46:58 2015 +0200 @@ -1,23 +1,54 @@ #pragma once -#include <QString> +#include "../main.h" #include "ast.h" namespace Script { enum TokenType { - TOK_Dollar, - TOK_Semicolon, - TOK_BraceLeft, - TOK_BraceRight, - TOK_BracketLeft, - TOK_BracketRight, - TOK_ParenLeft, - TOK_ParenRight, - TOK_String, - TOK_Symbol, - TOK_Number, - TOK_Any + TOK_DoubleEquals, // == + TOK_AngleLeftEquals, // <= + TOK_AngleRightEquals, // >= + TOK_DoubleAmperstand, // && + TOK_DoubleBar, // || + TOK_Dollar, // $ + TOK_Colon, // : + TOK_Semicolon, // ; + TOK_Dot, // . + TOK_Comma, // , + TOK_Equals, // = + TOK_AngleLeft, // < + TOK_AngleRight, // > + TOK_QuestionMark, // ? + TOK_BraceLeft, // { + TOK_BraceRight, // } + TOK_BracketLeft, // [ + TOK_BracketRight, // ] + TOK_ParenLeft, // ( + TOK_ParenRight, // ) + TOK_Minus, // - + TOK_Plus, // + + TOK_Asterisk, // * + TOK_Slash, // / + TOK_Backslash, // \. + TOK_Amperstand, // & + TOK_Caret, // ^ + TOK_Bar, // | + TOK_Exclamation, // ! + TOK_At, // @ + TOK_Pound, // # + TOK_Tilde, // ~ + TOK_GraveAccent, // ` + TOK_Percent, // % + TOK_String, // "foo" + TOK_Symbol, // bar + TOK_Number, // 42 + TOK_Any // for next() and friends, a token never has this + }; + + enum + { + LastNamedToken = TOK_Percent }; enum Type @@ -84,9 +115,12 @@ bool peekNext(Token& tok); const SavedPosition& position() const; void setPosition(const SavedPosition& pos); + QString preprocessedScript() const { return QString::fromAscii (m_data); } private: - QString m_data; + QString m_script; + QByteArray m_data; + QVector<int> m_lineEndings; SavedPosition m_position; Token m_token; AstNode* m_astRoot;