From 0cfeab622d6c22782ab208ba4714d101b6033751 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 28 Jun 2010 13:28:50 +0200 Subject: [PATCH] added storage class for local variable declarations; added checks for variable re-declaration --- CMakeLists.txt | 3 +- components/compiler/fileparser.cpp | 3 +- components/compiler/fileparser.hpp | 2 + components/compiler/lineparser.cpp | 18 +++++++- components/compiler/lineparser.hpp | 7 ++- components/compiler/locals.cpp | 67 ++++++++++++++++++++++++++++ components/compiler/locals.hpp | 36 +++++++++++++++ components/compiler/scriptparser.cpp | 6 ++- components/compiler/scriptparser.hpp | 6 ++- 9 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 components/compiler/locals.cpp create mode 100644 components/compiler/locals.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5377ea920..a3944ba57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,8 @@ set(COMPILER components/compiler/errorhandler.cpp components/compiler/fileparser.cpp components/compiler/scriptparser.cpp components/compiler/lineparser.cpp components/compiler/skipparser.cpp components/compiler/parser.cpp components/compiler/scanner.cpp - components/compiler/streamerrorhandler.cpp) + components/compiler/streamerrorhandler.cpp + components/compiler/locals.cpp) file(GLOB COMPILER_HEADER components/compiler/*.hpp) source_group(compiler FILES ${COMPILER} ${COMPILER_HEADER}) diff --git a/components/compiler/fileparser.cpp b/components/compiler/fileparser.cpp index 9894bce67..676bbec95 100644 --- a/components/compiler/fileparser.cpp +++ b/components/compiler/fileparser.cpp @@ -9,7 +9,7 @@ namespace Compiler { FileParser::FileParser (ErrorHandler& errorHandler, Context& context) : Parser (errorHandler, context), - mScriptParser (errorHandler, context, true), + mScriptParser (errorHandler, context, mLocals, true), mState (BeginState) {} @@ -88,6 +88,7 @@ namespace Compiler mState = BeginState; mName.clear(); mScriptParser.reset(); + mLocals.clear(); } } diff --git a/components/compiler/fileparser.hpp b/components/compiler/fileparser.hpp index 81b8025ce..dc0353ea4 100644 --- a/components/compiler/fileparser.hpp +++ b/components/compiler/fileparser.hpp @@ -3,6 +3,7 @@ #include "parser.hpp" #include "scriptparser.hpp" +#include "locals.hpp" namespace Compiler { @@ -19,6 +20,7 @@ namespace Compiler ScriptParser mScriptParser; State mState; std::string mName; + Locals mLocals; public: diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 6c8c3f735..6eda26748 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -7,11 +7,12 @@ #include "context.hpp" #include "errorhandler.hpp" #include "skipparser.hpp" +#include "locals.hpp" namespace Compiler { - LineParser::LineParser (ErrorHandler& errorHandler, Context& context) - : Parser (errorHandler, context), mState (BeginState) + LineParser::LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals) + : Parser (errorHandler, context), mLocals (locals), mState (BeginState) {} bool LineParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) @@ -37,7 +38,20 @@ namespace Compiler return false; } + char type = mLocals.getType (name); + + if (type!=' ') + { + getErrorHandler().error ("can't re-declare local variable", loc); + SkipParser skip (getErrorHandler(), getContext()); + scanner.scan (skip); + return false; + } + std::cout << "declaring local variable: " << name << std::endl; + mLocals.declare (mState==ShortState ? 's' : (mState==LongState ? 'l' : 'f'), + name); + mState = EndState; return true; } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 420315551..3c2ed309f 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -5,6 +5,8 @@ namespace Compiler { + class Locals; + /// \brief Line parser, to be used in console scripts and as part of ScriptParser class LineParser : public Parser @@ -15,12 +17,13 @@ namespace Compiler ShortState, LongState, FloatState, EndState }; - + + Locals& mLocals; State mState; public: - LineParser (ErrorHandler& errorHandler, Context& context); + LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals); virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); ///< Handle an int token. diff --git a/components/compiler/locals.cpp b/components/compiler/locals.cpp new file mode 100644 index 000000000..fe0974cf3 --- /dev/null +++ b/components/compiler/locals.cpp @@ -0,0 +1,67 @@ + +#include "locals.hpp" + +#include +#include +#include + +namespace Compiler +{ + const std::vector& Locals::get (char type) const + { + switch (type) + { + case 's': return mShorts; + case 'l': return mLongs; + case 'f': return mFloats; + } + + throw std::logic_error ("unknown variable type"); + } + + bool Locals::search (char type, const std::string& name) const + { + const std::vector& collection = get (type); + + return std::find (collection.begin(), collection.end(), name)!=collection.end(); + } + + std::vector& Locals::get (char type) + { + switch (type) + { + case 's': return mShorts; + case 'l': return mLongs; + case 'f': return mFloats; + } + + throw std::logic_error ("unknown variable type"); + } + + char Locals::getType (const std::string& name) const + { + if (search ('s', name)) + return 's'; + + if (search ('l', name)) + return 'l'; + + if (search ('f', name)) + return 'f'; + + return ' '; + } + + void Locals::declare (char type, const std::string& name) + { + get (type).push_back (name); + } + + void Locals::clear() + { + get ('s').clear(); + get ('l').clear(); + get ('f').clear(); + } +} + diff --git a/components/compiler/locals.hpp b/components/compiler/locals.hpp new file mode 100644 index 000000000..4e4d5c765 --- /dev/null +++ b/components/compiler/locals.hpp @@ -0,0 +1,36 @@ +#ifndef COMPILER_LOCALS_H_INCLUDED +#define COMPILER_LOCALS_H_INCLUDED + +#include +#include + +namespace Compiler +{ + /// \brief Local variable declarations + + class Locals + { + std::vector mShorts; + std::vector mLongs; + std::vector mFloats; + + const std::vector& get (char type) const; + + bool search (char type, const std::string& name) const; + + std::vector& get (char type); + + public: + + char getType (const std::string& name) const; + ///< 's': short, 'l': long, 'f': float, ' ': does not exist. + + void declare (char type, const std::string& name); + ///< declares a variable. + + void clear(); + ///< remove all declarations. + }; +} + +#endif diff --git a/components/compiler/scriptparser.cpp b/components/compiler/scriptparser.cpp index 769cc5ab2..fb3d47e66 100644 --- a/components/compiler/scriptparser.cpp +++ b/components/compiler/scriptparser.cpp @@ -5,8 +5,10 @@ namespace Compiler { - ScriptParser::ScriptParser (ErrorHandler& errorHandler, Context& context, bool end) - : Parser (errorHandler, context), mLineParser (errorHandler, context), mEnd (end) + ScriptParser::ScriptParser (ErrorHandler& errorHandler, Context& context, + Locals& locals, bool end) + : Parser (errorHandler, context), mLineParser (errorHandler, context, locals), + mLocals (locals), mEnd (end) {} bool ScriptParser::parseName (const std::string& name, const TokenLoc& loc, diff --git a/components/compiler/scriptparser.hpp b/components/compiler/scriptparser.hpp index 6933b7d08..45c637947 100644 --- a/components/compiler/scriptparser.hpp +++ b/components/compiler/scriptparser.hpp @@ -6,17 +6,21 @@ namespace Compiler { + class Locals; + // Script parser, to be used in dialogue scripts and as part of FileParser class ScriptParser : public Parser { LineParser mLineParser; + Locals& mLocals; bool mEnd; public: /// \param end of script is marked by end keyword. - ScriptParser (ErrorHandler& errorHandler, Context& context, bool end = false); + ScriptParser (ErrorHandler& errorHandler, Context& context, Locals& locals, + bool end = false); virtual bool parseName (const std::string& name, const TokenLoc& loc, Scanner& scanner);