From ed676b2d9a6ec19004f5aa27bc7e461570788ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Tue, 18 Aug 2015 15:21:38 +0300 Subject: [PATCH] Scripting|Info|libcore: No exception when parsing an embedded script ScriptLex can now be told to stop parsing statements when it encounters a mismatched closing }. This occurs normally when a Doomsday Script block is parsed inside an Info document, because the Info parser has no way of knowing how long the embedded script is unless it actually parses it using ScriptLex. Previously ScriptLex just blindly tried to read statements until it hit an exception. --- .../libcore/include/de/scriptsys/scriptlex.h | 20 ++++++++++++--- doomsday/sdk/libcore/src/data/info.cpp | 25 ++++++------------- .../sdk/libcore/src/scriptsys/scriptlex.cpp | 10 +++++++- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/doomsday/sdk/libcore/include/de/scriptsys/scriptlex.h b/doomsday/sdk/libcore/include/de/scriptsys/scriptlex.h index f1ad21e041..a39913c174 100644 --- a/doomsday/sdk/libcore/include/de/scriptsys/scriptlex.h +++ b/doomsday/sdk/libcore/include/de/scriptsys/scriptlex.h @@ -14,15 +14,17 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ - + #ifndef LIBDENG2_SCRIPTLEX_H #define LIBDENG2_SCRIPTLEX_H #include "../Lex" #include "../TokenBuffer" +#include + namespace de { #ifdef WIN32 @@ -88,17 +90,25 @@ class DENG2_PUBLIC ScriptLex : public Lex static String const SCOPE_ASSIGN; static String const WEAK_ASSIGN; + enum Behavior + { + DefaultBehavior = 0, + StopAtMismatchedCloseBrace = 0x1 ///< Mismatched } is treated as end of input. + }; + Q_DECLARE_FLAGS(Behaviors, Behavior) + public: ScriptLex(String const &input = ""); /** * Analyze one complete statement from the input. * - * @param output Buffer for output tokens. + * @param output Buffer for output tokens. + * @param behavior Parsing behavior. * * @return The number of tokens added to the output token buffer. */ - duint getStatement(TokenBuffer &output); + duint getStatement(TokenBuffer &output, Behaviors const &behavior = DefaultBehavior); /** * Parse a string. @@ -134,6 +144,8 @@ class DENG2_PUBLIC ScriptLex : public Lex static ddouble tokenToNumber(Token const &token); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptLex::Behaviors) + } // namespace de #endif /* LIBDENG2_SCRIPTLEX_H */ diff --git a/doomsday/sdk/libcore/src/data/info.cpp b/doomsday/sdk/libcore/src/data/info.cpp index e32fb87173..68fd5e4670 100644 --- a/doomsday/sdk/libcore/src/data/info.cpp +++ b/doomsday/sdk/libcore/src/data/info.cpp @@ -350,29 +350,20 @@ DENG2_PIMPL(Info) return value; } - InfoValue parseScript(int numStatements = 0) + InfoValue parseScript(int requiredStatementCount = 0) { int startPos = cursor - 1; String remainder = content.substr(startPos); ScriptLex lex(remainder); - try - { - TokenBuffer tokens; - int count = 0; - // Read an appropriate number of statements. - while(lex.getStatement(tokens)) - { - if(numStatements > 0 && ++count == numStatements) - goto success; - } - throw SyntaxError("Info::parseScript", - QString("Unexpected end of script starting at line %1").arg(currentLine)); -success:; - } - catch(ScriptLex::MismatchedBracketError const &) + TokenBuffer tokens; + int count = 0; + + // Read an appropriate number of statements. + while(lex.getStatement(tokens, ScriptLex::StopAtMismatchedCloseBrace)) { - // A mismatched bracket signals the end of the script block. + if(requiredStatementCount > 0 && + ++count == requiredStatementCount) break; // We're good now. } // Continue parsing normally from here. diff --git a/doomsday/sdk/libcore/src/scriptsys/scriptlex.cpp b/doomsday/sdk/libcore/src/scriptsys/scriptlex.cpp index 9ff46a9a41..d8c1b20cec 100644 --- a/doomsday/sdk/libcore/src/scriptsys/scriptlex.cpp +++ b/doomsday/sdk/libcore/src/scriptsys/scriptlex.cpp @@ -60,7 +60,7 @@ String const ScriptLex::WEAK_ASSIGN("?="); ScriptLex::ScriptLex(String const &input) : Lex(input) {} -duint ScriptLex::getStatement(TokenBuffer &output) +duint ScriptLex::getStatement(TokenBuffer &output, Behaviors const &behavior) { // Get rid of the previous contents of the token buffer. output.clear(); @@ -90,6 +90,14 @@ duint ScriptLex::getStatement(TokenBuffer &output) // Tokens are primarily separated by whitespace. skipWhiteExceptNewline(); + if(behavior.testFlag(StopAtMismatchedCloseBrace) && + !bracketLevel[BRACKET_CURLY] && + peek() == '}') + { + // Don't read past the bracket. + break; + } + // This will be the first character of the token. QChar c = get();