mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.5 KiB
C++
128 lines
3.5 KiB
C++
#include "declarationparser.hpp"
|
|
|
|
#include <components/misc/strings/lower.hpp>
|
|
|
|
#include "context.hpp"
|
|
#include "errorhandler.hpp"
|
|
#include "extensions.hpp"
|
|
#include "locals.hpp"
|
|
#include "scanner.hpp"
|
|
#include "skipparser.hpp"
|
|
|
|
Compiler::DeclarationParser::DeclarationParser(ErrorHandler& errorHandler, const 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 != ' ')
|
|
getErrorHandler().warning("Local variable re-declaration", loc);
|
|
else
|
|
mLocals.declare(mType, name2);
|
|
|
|
mState = State_End;
|
|
return true;
|
|
}
|
|
else if (mState == State_End)
|
|
{
|
|
getErrorHandler().warning("Extra text after local variable declaration", loc);
|
|
SkipParser skip(getErrorHandler(), getContext());
|
|
scanner.scan(skip);
|
|
return false;
|
|
}
|
|
|
|
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!
|
|
if (const Extensions* extensions = getContext().getExtensions())
|
|
{
|
|
std::string argumentType;
|
|
bool hasExplicit = false;
|
|
char returnType;
|
|
if (extensions->isFunction(keyword, returnType, argumentType, hasExplicit))
|
|
getErrorHandler().warning("Local variable declaration shadows a function", loc);
|
|
}
|
|
|
|
return parseName(loc.mLiteral, loc, scanner);
|
|
}
|
|
else if (mState == State_End)
|
|
{
|
|
getErrorHandler().warning("Extra text after local variable declaration", loc);
|
|
SkipParser skip(getErrorHandler(), getContext());
|
|
scanner.scan(skip);
|
|
return false;
|
|
}
|
|
|
|
return Parser::parseKeyword(keyword, loc, scanner);
|
|
}
|
|
|
|
bool Compiler::DeclarationParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner)
|
|
{
|
|
if (mState == State_End)
|
|
{
|
|
if (code != Scanner::S_newline)
|
|
{
|
|
getErrorHandler().warning("Extra text after local variable declaration", loc);
|
|
SkipParser skip(getErrorHandler(), getContext());
|
|
scanner.scan(skip);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return Parser::parseSpecial(code, loc, scanner);
|
|
}
|
|
|
|
bool Compiler::DeclarationParser::parseInt(int value, const TokenLoc& loc, Scanner& scanner)
|
|
{
|
|
if (mState == State_Name)
|
|
{
|
|
// Allow integers to be used as variable names
|
|
getErrorHandler().warning("Integer is used as a local variable name", loc);
|
|
return parseName(loc.mLiteral, loc, scanner);
|
|
}
|
|
return Parser::parseInt(value, loc, scanner);
|
|
}
|
|
|
|
void Compiler::DeclarationParser::reset()
|
|
{
|
|
mState = State_Begin;
|
|
}
|