factored out declaration parser

actorid
Marc Zinnschlag 11 years ago
parent 2b2ac6f62b
commit 3147aebf75

@ -55,7 +55,7 @@ add_component_dir (files
add_component_dir (compiler add_component_dir (compiler
context controlparser errorhandler exception exprparser extensions fileparser generator context controlparser errorhandler exception exprparser extensions fileparser generator
lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler
stringparser tokenloc nullerrorhandler opcodes extensions0 stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser
) )
add_component_dir (interpreter add_component_dir (interpreter

@ -0,0 +1,79 @@
#include "declarationparser.hpp"
#include <components/misc/stringops.hpp>
#include "scanner.hpp"
#include "errorhandler.hpp"
#include "skipparser.hpp"
#include "locals.hpp"
Compiler::DeclarationParser::DeclarationParser (ErrorHandler& errorHandler, Context& context,
Locals& locals)
: Parser (errorHandler, context), mLocals (locals), mState (State_Begin), mType (0)
{}
bool Compiler::DeclarationParser::parseName (const std::string& name, const TokenLoc& loc,
Scanner& scanner)
{
if (mState==State_Name)
{
std::string name2 = Misc::StringUtils::lowerCase (name);
char type = mLocals.getType (name2);
if (type!=' ')
{
/// \todo add option to make re-declared local variables an error
getErrorHandler().warning ("can't re-declare local variable (ignoring declaration)",
loc);
SkipParser skip (getErrorHandler(), getContext());
scanner.scan (skip);
mState = State_End;
return true;
}
mLocals.declare (mType, name2);
mState = State_End;
return true;
}
return Parser::parseName (name, loc, scanner);
}
bool Compiler::DeclarationParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
{
if (mState==State_Begin)
{
switch (keyword)
{
case Scanner::K_short: mType = 's'; break;
case Scanner::K_long: mType = 'l'; break;
case Scanner::K_float: mType = 'f'; break;
default: mType = 0;
}
if (mType)
{
mState = State_Name;
return true;
}
}
else if (mState==State_Name)
{
// allow keywords to be used as local variable names. MW script compiler, you suck!
/// \todo option to disable this atrocity.
return parseName (loc.mLiteral, loc, scanner);
}
return Parser::parseKeyword (keyword, loc, scanner);
}
bool Compiler::DeclarationParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
{
if (code==Scanner::S_newline && mState==State_End)
return false;
return Parser::parseSpecial (code, loc, scanner);
}

@ -0,0 +1,41 @@
#ifndef COMPILER_DECLARATIONPARSER_H_INCLUDED
#define COMPILER_DECLARATIONPARSER_H_INCLUDED
#include "parser.hpp"
namespace Compiler
{
class Locals;
class DeclarationParser : public Parser
{
enum State
{
State_Begin, State_Name, State_End
};
Locals& mLocals;
State mState;
char mType;
public:
DeclarationParser (ErrorHandler& errorHandler, Context& context, Locals& locals);
virtual bool parseName (const std::string& name, const TokenLoc& loc,
Scanner& scanner);
///< Handle a name token.
/// \return fetch another token?
virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner);
///< Handle a keyword token.
/// \return fetch another token?
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
///< Handle a special character token.
/// \return fetch another token?
};
}
#endif

@ -1,6 +1,8 @@
#include "lineparser.hpp" #include "lineparser.hpp"
#include <components/misc/stringops.hpp>
#include "scanner.hpp" #include "scanner.hpp"
#include "context.hpp" #include "context.hpp"
#include "errorhandler.hpp" #include "errorhandler.hpp"
@ -8,7 +10,7 @@
#include "locals.hpp" #include "locals.hpp"
#include "generator.hpp" #include "generator.hpp"
#include "extensions.hpp" #include "extensions.hpp"
#include <components/misc/stringops.hpp> #include "declarationparser.hpp"
namespace Compiler namespace Compiler
{ {
@ -82,37 +84,6 @@ namespace Compiler
bool LineParser::parseName (const std::string& name, const TokenLoc& loc, bool LineParser::parseName (const std::string& name, const TokenLoc& loc,
Scanner& scanner) Scanner& scanner)
{ {
if (mState==ShortState || mState==LongState || mState==FloatState)
{
if (!getContext().canDeclareLocals())
{
getErrorHandler().error ("local variables can't be declared in this context", loc);
SkipParser skip (getErrorHandler(), getContext());
scanner.scan (skip);
return false;
}
std::string name2 = Misc::StringUtils::lowerCase (name);
char type = mLocals.getType (name2);
if (type!=' ')
{
/// \todo add option to make re-declared local variables an error
getErrorHandler().warning ("can't re-declare local variable", loc);
SkipParser skip (getErrorHandler(), getContext());
scanner.scan (skip);
mState = EndState;
return true;
}
mLocals.declare (mState==ShortState ? 's' : (mState==LongState ? 'l' : 'f'),
name2);
mState = EndState;
return true;
}
if (mState==SetState) if (mState==SetState)
{ {
std::string name2 = Misc::StringUtils::lowerCase (name); std::string name2 = Misc::StringUtils::lowerCase (name);
@ -303,9 +274,26 @@ namespace Compiler
{ {
switch (keyword) switch (keyword)
{ {
case Scanner::K_short: mState = ShortState; return true; case Scanner::K_short:
case Scanner::K_long: mState = LongState; return true; case Scanner::K_long:
case Scanner::K_float: mState = FloatState; return true; case Scanner::K_float:
{
if (!getContext().canDeclareLocals())
{
getErrorHandler().error (
"local variables can't be declared in this context", loc);
SkipParser skip (getErrorHandler(), getContext());
scanner.scan (skip);
return true;
}
DeclarationParser declaration (getErrorHandler(), getContext(), mLocals);
if (declaration.parseKeyword (keyword, loc, scanner))
scanner.scan (declaration);
return true;
}
case Scanner::K_set: mState = SetState; return true; case Scanner::K_set: mState = SetState; return true;
case Scanner::K_messagebox: mState = MessageState; return true; case Scanner::K_messagebox: mState = MessageState; return true;
@ -370,12 +358,6 @@ namespace Compiler
mState = EndState; mState = EndState;
return true; return true;
} }
else if (mState==ShortState || mState==LongState || mState==FloatState)
{
// allow keywords to be used as local variable names. MW script compiler, you suck!
/// \todo option to disable this atrocity.
return parseName (loc.mLiteral, loc, scanner);
}
if (mAllowExpression) if (mAllowExpression)
{ {

@ -20,7 +20,6 @@ namespace Compiler
enum State enum State
{ {
BeginState, BeginState,
ShortState, LongState, FloatState,
SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState, SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState,
SetMemberVarState, SetMemberVarState2, SetMemberVarState, SetMemberVarState2,
MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState, MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState,

Loading…
Cancel
Save