mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-29 10:56:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			127 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			127 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;
 | |
| }
 |