forked from teamnwah/openmw-tes3coop
reimplemented expression parsing as a separate parser (still only handling non-negative integers)
This commit is contained in:
parent
10cb9d3dab
commit
bceb7ebcbd
7 changed files with 184 additions and 34 deletions
|
@ -66,18 +66,11 @@ set(MISC_HEADER components/misc/fileops.hpp components/misc/slice_array.hpp
|
||||||
components/misc/stringops.hpp)
|
components/misc/stringops.hpp)
|
||||||
source_group(misc FILES ${MISC} ${MISC_HEADER})
|
source_group(misc FILES ${MISC} ${MISC_HEADER})
|
||||||
|
|
||||||
set(COMPILER components/compiler/errorhandler.cpp
|
file(GLOB COMPILER components/compiler/*.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/locals.cpp components/compiler/literals.cpp
|
|
||||||
components/compiler/output.cpp components/compiler/generator.cpp)
|
|
||||||
file(GLOB COMPILER_HEADER components/compiler/*.hpp)
|
file(GLOB COMPILER_HEADER components/compiler/*.hpp)
|
||||||
source_group(compiler FILES ${COMPILER} ${COMPILER_HEADER})
|
source_group(compiler FILES ${COMPILER} ${COMPILER_HEADER})
|
||||||
|
|
||||||
set(INTERPRETER components/interpreter/runtime.cpp components/interpreter/interpreter.cpp
|
file(GLOB INTERPRETER components/interpreter/*.cpp)
|
||||||
components/interpreter/installopcodes.cpp)
|
|
||||||
file(GLOB INTERPRETER_HEADER components/interpreter/*.hpp)
|
file(GLOB INTERPRETER_HEADER components/interpreter/*.hpp)
|
||||||
source_group(interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER})
|
source_group(interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER})
|
||||||
|
|
||||||
|
|
65
components/compiler/exprparser.cpp
Normal file
65
components/compiler/exprparser.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
#include "exprparser.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "generator.hpp"
|
||||||
|
|
||||||
|
namespace Compiler
|
||||||
|
{
|
||||||
|
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
|
Literals& literals)
|
||||||
|
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||||
|
{
|
||||||
|
Operand operand;
|
||||||
|
operand.mType = 'l';
|
||||||
|
operand.mInteger = value;
|
||||||
|
|
||||||
|
mOperands.push_back (operand);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExprParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
||||||
|
{
|
||||||
|
return Parser::parseFloat (value, loc, scanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExprParser::parseName (const std::string& name, const TokenLoc& loc,
|
||||||
|
Scanner& scanner)
|
||||||
|
{
|
||||||
|
return Parser::parseName (name, loc, scanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||||
|
{
|
||||||
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExprParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||||
|
{
|
||||||
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExprParser::reset()
|
||||||
|
{
|
||||||
|
mOperands.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
char ExprParser::write (std::vector<Interpreter::Type_Code>& code)
|
||||||
|
{
|
||||||
|
if (mOperands.empty())
|
||||||
|
throw std::logic_error ("empty expression");
|
||||||
|
|
||||||
|
Operand operand = mOperands[mOperands.size()-1];
|
||||||
|
mOperands.clear();
|
||||||
|
|
||||||
|
Generator::pushInt (code, mLiterals, operand.mInteger);
|
||||||
|
|
||||||
|
return operand.mType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
67
components/compiler/exprparser.hpp
Normal file
67
components/compiler/exprparser.hpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef COMPILER_EXPRPARSER_H_INCLUDED
|
||||||
|
#define COMPILER_EXPRPARSER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <components/interpreter/types.hpp>
|
||||||
|
|
||||||
|
#include "parser.hpp"
|
||||||
|
|
||||||
|
namespace Compiler
|
||||||
|
{
|
||||||
|
class Locals;
|
||||||
|
class Literals;
|
||||||
|
|
||||||
|
class ExprParser : public Parser
|
||||||
|
{
|
||||||
|
struct Operand
|
||||||
|
{
|
||||||
|
char mType;
|
||||||
|
int mInteger;
|
||||||
|
float mFloat;
|
||||||
|
};
|
||||||
|
|
||||||
|
Locals& mLocals;
|
||||||
|
Literals& mLiterals;
|
||||||
|
std::vector<Operand> mOperands;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
|
Literals& literals);
|
||||||
|
///< constructor
|
||||||
|
|
||||||
|
char getType() const;
|
||||||
|
///< Return type of parsed expression ('l' integer, 'f' float)
|
||||||
|
|
||||||
|
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
|
||||||
|
///< Handle an int token.
|
||||||
|
/// \return fetch another token?
|
||||||
|
|
||||||
|
virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner);
|
||||||
|
///< Handle a float token.
|
||||||
|
/// \return fetch another token?
|
||||||
|
|
||||||
|
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?
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
///< Reset parser to clean state.
|
||||||
|
|
||||||
|
char write (std::vector<Interpreter::Type_Code>& code);
|
||||||
|
///< Generate code for parsed expression.
|
||||||
|
/// \return Type ('l': integer, 'f': float)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,6 +2,8 @@
|
||||||
#include "generator.hpp"
|
#include "generator.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include "literals.hpp"
|
#include "literals.hpp"
|
||||||
|
|
||||||
|
@ -63,6 +65,11 @@ namespace
|
||||||
code.push_back (segment5 (3));
|
code.push_back (segment5 (3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opFloatToInt (Compiler::Generator::CodeContainer& code)
|
||||||
|
{
|
||||||
|
assert (0); // not implemented
|
||||||
|
}
|
||||||
|
|
||||||
void opStoreLocalShort (Compiler::Generator::CodeContainer& code)
|
void opStoreLocalShort (Compiler::Generator::CodeContainer& code)
|
||||||
{
|
{
|
||||||
code.push_back (segment5 (0));
|
code.push_back (segment5 (0));
|
||||||
|
@ -83,20 +90,36 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
namespace Generator
|
namespace Generator
|
||||||
{
|
{
|
||||||
void assignIntToLocal (CodeContainer& code, Literals& literals, char localType,
|
void pushInt (CodeContainer& code, Literals& literals, int value)
|
||||||
int localIndex, int value)
|
|
||||||
{
|
{
|
||||||
int index = literals.addInteger (value);
|
int index = literals.addInteger (value);
|
||||||
|
|
||||||
opPushInt (code, localIndex);
|
|
||||||
opPushInt (code, index);
|
opPushInt (code, index);
|
||||||
opFetchIntLiteral (code);
|
opFetchIntLiteral (code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assignToLocal (CodeContainer& code, char localType,
|
||||||
|
int localIndex, const CodeContainer& value, char valueType)
|
||||||
|
{
|
||||||
|
opPushInt (code, localIndex);
|
||||||
|
|
||||||
|
std::copy (value.begin(), value.end(), std::back_inserter (code));
|
||||||
|
|
||||||
|
if (localType!=valueType)
|
||||||
|
{
|
||||||
|
if (localType=='f' && valueType=='l')
|
||||||
|
{
|
||||||
|
opIntToFloat (code);
|
||||||
|
}
|
||||||
|
else if ((localType=='l' || localType=='s') && valueType=='f')
|
||||||
|
{
|
||||||
|
opFloatToInt (code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (localType)
|
switch (localType)
|
||||||
{
|
{
|
||||||
case 'f':
|
case 'f':
|
||||||
|
|
||||||
opIntToFloat (code);
|
|
||||||
opStoreLocalFloat (code);
|
opStoreLocalFloat (code);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,10 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
typedef std::vector<Interpreter::Type_Code> CodeContainer;
|
typedef std::vector<Interpreter::Type_Code> CodeContainer;
|
||||||
|
|
||||||
void assignIntToLocal (CodeContainer& code, Literals& literals, char localType,
|
void pushInt (CodeContainer& code, Literals& literals, int value);
|
||||||
int localIndex, int value);
|
|
||||||
|
void assignToLocal (CodeContainer& code, char localType,
|
||||||
|
int localIndex, const CodeContainer& value, char valueType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,22 +13,11 @@ namespace Compiler
|
||||||
LineParser::LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
LineParser::LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
Literals& literals, std::vector<Interpreter::Type_Code>& code)
|
Literals& literals, std::vector<Interpreter::Type_Code>& code)
|
||||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mCode (code),
|
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mCode (code),
|
||||||
mState (BeginState)
|
mState (BeginState), mExprParser (errorHandler, context, locals, literals)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool LineParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
bool LineParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
if (mState==SetLocalToState)
|
|
||||||
{
|
|
||||||
Generator::assignIntToLocal (mCode, mLiterals, mLocals.getType (mName),
|
|
||||||
mLocals.getIndex (mName), value);
|
|
||||||
|
|
||||||
mState = EndState;
|
|
||||||
mName.clear();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parser::parseInt (value, loc, scanner);
|
return Parser::parseInt (value, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +93,16 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
||||||
{
|
{
|
||||||
mState = SetLocalToState;
|
mExprParser.reset();
|
||||||
|
scanner.scan (mExprParser);
|
||||||
|
|
||||||
|
std::vector<Interpreter::Type_Code> code;
|
||||||
|
char type = mExprParser.write (code);
|
||||||
|
|
||||||
|
Generator::assignToLocal (mCode, mLocals.getType (mName),
|
||||||
|
mLocals.getIndex (mName), code, type);
|
||||||
|
|
||||||
|
mState = EndState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <components/interpreter/types.hpp>
|
#include <components/interpreter/types.hpp>
|
||||||
|
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
|
#include "exprparser.hpp"
|
||||||
|
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,7 @@ namespace Compiler
|
||||||
std::vector<Interpreter::Type_Code>& mCode;
|
std::vector<Interpreter::Type_Code>& mCode;
|
||||||
State mState;
|
State mState;
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
ExprParser mExprParser;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue