mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 06:45:35 +00:00
added storage class for local variable declarations; added checks for variable re-declaration
This commit is contained in:
parent
21e0182ae2
commit
0cfeab622d
9 changed files with 139 additions and 9 deletions
|
@ -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})
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
67
components/compiler/locals.cpp
Normal file
67
components/compiler/locals.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
|
||||
#include "locals.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
const std::vector<std::string>& 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<std::string>& collection = get (type);
|
||||
|
||||
return std::find (collection.begin(), collection.end(), name)!=collection.end();
|
||||
}
|
||||
|
||||
std::vector<std::string>& 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();
|
||||
}
|
||||
}
|
||||
|
36
components/compiler/locals.hpp
Normal file
36
components/compiler/locals.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef COMPILER_LOCALS_H_INCLUDED
|
||||
#define COMPILER_LOCALS_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
/// \brief Local variable declarations
|
||||
|
||||
class Locals
|
||||
{
|
||||
std::vector<std::string> mShorts;
|
||||
std::vector<std::string> mLongs;
|
||||
std::vector<std::string> mFloats;
|
||||
|
||||
const std::vector<std::string>& get (char type) const;
|
||||
|
||||
bool search (char type, const std::string& name) const;
|
||||
|
||||
std::vector<std::string>& 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
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue