holy shit thats a lot of changed to asmrigs
This commit is contained in:
132
asmrigs/as/as.cpp
Normal file
132
asmrigs/as/as.cpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#include "asmrigs/as.h"
|
||||||
|
#include "tier2/tokenizer.h"
|
||||||
|
#include "asmrigs/tokenparser.h"
|
||||||
|
|
||||||
|
struct ObjectHeader_t
|
||||||
|
{
|
||||||
|
uint8_t m_magic[4];
|
||||||
|
uint32_t m_uSymbolCount;
|
||||||
|
uint32_t m_uDatasCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EDataFlags: uint32_t
|
||||||
|
{
|
||||||
|
DATA_TYPE_DECLARE,
|
||||||
|
DATA_TYPE_USED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Data_t
|
||||||
|
{
|
||||||
|
uint64_t m_uDataSize;
|
||||||
|
uint64_t m_uDataOffsetSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Symbol_t
|
||||||
|
{
|
||||||
|
uint32_t m_uName;
|
||||||
|
uint32_t m_uData;
|
||||||
|
EDataFlags m_eDataFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EInstruction: uint8_t
|
||||||
|
{
|
||||||
|
I_NOP = 0,
|
||||||
|
|
||||||
|
I_PUSH = 3,
|
||||||
|
I_POP = 4,
|
||||||
|
|
||||||
|
I_CMP = 5,
|
||||||
|
|
||||||
|
I_JUMP = 6,
|
||||||
|
I_JZ = 7,
|
||||||
|
I_JNZ = 8,
|
||||||
|
I_JG = 9,
|
||||||
|
I_JGE = 10,
|
||||||
|
I_JLE = 11,
|
||||||
|
|
||||||
|
I_LOAD = 12,
|
||||||
|
I_STORE = 13,
|
||||||
|
I_LOADPTR = 14,
|
||||||
|
I_STOREPTR = 15,
|
||||||
|
I_LOADLIT = 16,
|
||||||
|
|
||||||
|
I_JSR = 20,
|
||||||
|
I_RET = 21,
|
||||||
|
};
|
||||||
|
|
||||||
|
CUtlBuffer<uint8_t> Assemble( const char *szAssembly, AsOptions_t stOptions )
|
||||||
|
{
|
||||||
|
CUtlVector<CUtlString> externalFunctions;
|
||||||
|
CUtlVector<CUtlString> publicFunctions;
|
||||||
|
CUtlVector<CUtlString> labels;
|
||||||
|
CUtlVector<Token_t> tokens = Tokenize(szAssembly);
|
||||||
|
Token_t *pTokens = tokens.GetData();
|
||||||
|
for ( int i = 0; i < tokens.GetSize()-2; )
|
||||||
|
{
|
||||||
|
if ( !tokens[i].m_bIsQuoted && tokens[i].m_szValue == "/" )
|
||||||
|
if ( !tokens[i+1].m_bIsQuoted && tokens[i+1].m_szValue == "/" )
|
||||||
|
if ( !tokens[i+2].m_bIsQuoted && tokens[i+2].m_szValue == "/" )
|
||||||
|
{
|
||||||
|
tokens.RemoveAt(i, 3);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
};
|
||||||
|
CTokenParser parser;
|
||||||
|
parser.m_pTokens = tokens.GetData();
|
||||||
|
parser.m_pTokensEnd = tokens.GetData()+tokens.GetSize();
|
||||||
|
parser.m_pCurrentToken = tokens.GetData()-1;
|
||||||
|
parser.Continue();
|
||||||
|
|
||||||
|
CUtlVector<uint8_t> commandStream;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (parser.IsEOF())
|
||||||
|
break;
|
||||||
|
CUtlString szCommand = parser.PeekToken();
|
||||||
|
parser.Continue();
|
||||||
|
if ( szCommand == "extrn" )
|
||||||
|
{
|
||||||
|
externalFunctions.AppendTail(parser.PeekToken());
|
||||||
|
parser.Continue();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( szCommand == "public" )
|
||||||
|
{
|
||||||
|
publicFunctions.AppendTail(parser.PeekToken());
|
||||||
|
parser.Continue();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( szCommand == "store" )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( szCommand == "load" )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( szCommand == "jsr" )
|
||||||
|
{
|
||||||
|
commandStream.AppendTail(I_JSR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( szCommand == "ret" )
|
||||||
|
{
|
||||||
|
commandStream.AppendTail(I_RET);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parser.IsEOF())
|
||||||
|
break;
|
||||||
|
if (!V_strcmp(parser.PeekToken(), ":"))
|
||||||
|
{
|
||||||
|
parser.Continue();
|
||||||
|
labels.AppendTail("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
V_printf("%s is not a valid instuction or label\n", szCommand.GetString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
18
asmrigs/as/main.cpp
Normal file
18
asmrigs/as/main.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "asmrigs/tokenparser.h"
|
||||||
|
#include "asmrigs/as.h"
|
||||||
|
#include "tier0/commandline.h"
|
||||||
|
#include "tier2/ifilesystem.h"
|
||||||
|
int main( int argc, char **argv )
|
||||||
|
{
|
||||||
|
CommandLine()->CreateCommandLine(argc, argv);
|
||||||
|
|
||||||
|
CreateInterfaceFn filesystemFactory = Sys_GetFactory("filesystem_std");
|
||||||
|
filesystem = (IFileSystem*)filesystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL);
|
||||||
|
|
||||||
|
IFileHandle *pFile = filesystem->Open(argv[1], FILEMODE_READ);
|
||||||
|
const char *szFileContents = filesystem->ReadString(pFile);
|
||||||
|
filesystem->Close(pFile);
|
||||||
|
|
||||||
|
Assemble(szFileContents, {});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -4,24 +4,17 @@
|
|||||||
#include "tier2/tokenizer.h"
|
#include "tier2/tokenizer.h"
|
||||||
#include "tier3/lexer.h"
|
#include "tier3/lexer.h"
|
||||||
|
|
||||||
#define B_LEXEL_INTERFACE_NAME "BLexer001"
|
|
||||||
|
|
||||||
|
abstract_class IBGenerator
|
||||||
enum EBWordType
|
|
||||||
{
|
|
||||||
BWORDTYPE_CONST_WORD,
|
|
||||||
|
|
||||||
BWORDTYPE_FUNCTION,
|
|
||||||
BWORDTYPE_FUNCTION_ARGS,
|
|
||||||
BWORDTYPE_FUNCTION_ARG,
|
|
||||||
BWORDTYPE_FUNCTION_SCOPE,
|
|
||||||
|
|
||||||
BWORDTYPE_RETURN,
|
|
||||||
};
|
|
||||||
|
|
||||||
abstract_class IBLexerWord: public ILexerWord
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual void AddExternSymbol( const char *szName ) = 0;
|
||||||
|
virtual void DefineFunction( const char *szName ) = 0;
|
||||||
|
virtual void Load( uint8_t uRegister, int iValue ) = 0;
|
||||||
|
virtual void Return() = 0;
|
||||||
|
virtual CUtlString GetAssembly() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define B_GENERATOR_INTERFACE_VERSION "BGenerator001"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
#include "brb.h"
|
|
||||||
|
|
||||||
abstract_class CBLexerWord: public IBLexerWord
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int GetType() override;
|
|
||||||
|
|
||||||
EBWordType m_eType;
|
|
||||||
};
|
|
||||||
|
|
||||||
int CBLexerWord::GetType()
|
|
||||||
{
|
|
||||||
return m_eType;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CBLexer: public ILexer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ILexerWord *ParseTokens( CUtlVector<Token_t> tokens ) override;
|
|
||||||
|
|
||||||
CBLexerWord *ParseFunctionBody( Token_t *&pToken, const Token_t *pEnding );
|
|
||||||
|
|
||||||
bool GetExpectedToken();
|
|
||||||
CUtlString GetStringLiteral();
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NEXT_TOKEN() \
|
|
||||||
pToken++; \
|
|
||||||
if (pToken == pEnding) \
|
|
||||||
goto eof \
|
|
||||||
|
|
||||||
ILexerWord *CBLexer::ParseTokens( CUtlVector<Token_t> tokens )
|
|
||||||
{
|
|
||||||
Token_t *pCurrentToken = tokens.GetData();
|
|
||||||
Token_t *pEndingToken = tokens.GetData() + tokens.GetSize();
|
|
||||||
CBLexerWord *pGlobalWord = new CBLexerWord;
|
|
||||||
|
|
||||||
|
|
||||||
return pGlobalWord;
|
|
||||||
};
|
|
||||||
@@ -1,48 +1,35 @@
|
|||||||
#include "brb.h"
|
#include "brb.h"
|
||||||
|
#include "asmrigs/tokenparser.h"
|
||||||
#include "tier0/commandline.h"
|
#include "tier0/commandline.h"
|
||||||
#include "tier2/ifilesystem.h"
|
#include "tier2/ifilesystem.h"
|
||||||
|
|
||||||
|
IBGenerator *g_pGenerator;
|
||||||
|
|
||||||
class CTokenParser
|
class CBGenerator: public IBGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const char *PeekToken();
|
virtual void AddExternSymbol( const char *szName ) override;
|
||||||
bool IsToken( const char *szString );
|
virtual void DefineFunction( const char *szName ) override;
|
||||||
const char *PeekStringLiteral();
|
virtual CUtlString GetAssembly() override;
|
||||||
bool Continue();
|
CUtlVector<CUtlString> m_externalSymbols;
|
||||||
|
CUtlString m_szAssembly;
|
||||||
Token_t *m_pTokens;
|
|
||||||
Token_t *m_pTokensEnd;
|
|
||||||
Token_t *m_pCurrentToken;
|
|
||||||
};
|
};
|
||||||
|
EXPOSE_INTERFACE(CBGenerator, IBGenerator, B_GENERATOR_INTERFACE_VERSION);
|
||||||
|
|
||||||
const char *CTokenParser::PeekToken()
|
void CBGenerator::AddExternSymbol( const char *szName )
|
||||||
{
|
{
|
||||||
if ( m_pCurrentToken->m_bIsQuoted )
|
m_externalSymbols.AppendTail(szName);
|
||||||
return NULL;
|
|
||||||
return m_pCurrentToken->m_szValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTokenParser::IsToken( const char *szString )
|
void CBGenerator::DefineFunction( const char *szName )
|
||||||
{
|
{
|
||||||
if ( !V_strcmp(szString, m_pCurrentToken->m_szValue))
|
m_szAssembly.AppendTail(CUtlString("public %s\n", szName));
|
||||||
return true;
|
m_szAssembly.AppendTail(CUtlString("%s:\n", szName));
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *CTokenParser::PeekStringLiteral()
|
|
||||||
{
|
|
||||||
if ( !m_pCurrentToken->m_bIsQuoted )
|
|
||||||
return NULL;
|
|
||||||
return m_pCurrentToken->m_szValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTokenParser::Continue()
|
CUtlString CBGenerator::GetAssembly()
|
||||||
{
|
{
|
||||||
m_pCurrentToken++;
|
return m_szAssembly;
|
||||||
if ( m_pCurrentToken == m_pTokensEnd )
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompileErrorExpectedToken( Token_t *pToken, const char *szToken )
|
void CompileErrorExpectedToken( Token_t *pToken, const char *szToken )
|
||||||
@@ -54,32 +41,235 @@ void CompileErrorExpectedToken( Token_t *pToken, const char *szToken )
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BExpression_t
|
void CompileErrorUnexpectedToken( Token_t *pToken )
|
||||||
{
|
{
|
||||||
enum BExpressionType
|
if (pToken->m_bIsQuoted)
|
||||||
{
|
V_printf("%d:%d: unexpected string literal\n", pToken->m_iLine, pToken->m_iCharacter );
|
||||||
BEXPRESSION_TYPE_NEW,
|
else
|
||||||
BEXPRESSION_TYPE_ADD,
|
V_printf("%d:%d: unexpected %s\n", pToken->m_iLine, pToken->m_iCharacter, pToken->m_szValue.GetString());
|
||||||
BEXPRESSION_TYPE_SUBTRACT,
|
exit(1);
|
||||||
} m_eType;
|
}
|
||||||
CUtlVector<BExpression_t> m_children;
|
void CompileErrorGotRValue( Token_t *pToken )
|
||||||
|
{
|
||||||
|
V_printf("%d:%d: got rvalue when expected lvalue\n", pToken->m_iLine, pToken->m_iCharacter );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EBValueType
|
||||||
|
{
|
||||||
|
EBVALUE_TYPE_UNKNOWN,
|
||||||
|
EBVALUE_TYPE_INT_LITERAL,
|
||||||
|
EBVALUE_TYPE_VARIABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
BExpression_t ParseVar( CTokenParser *pParser )
|
struct BValue_t
|
||||||
|
{
|
||||||
|
enum EBValueType m_eType;
|
||||||
|
int m_iLiteral;
|
||||||
|
const char *m_szVarName;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EBValueNodeOp
|
||||||
|
{
|
||||||
|
EBVALUE_OP_NOTHING,
|
||||||
|
EBVALUE_OP_VALUE,
|
||||||
|
EBVALUE_OP_READ_PTR,
|
||||||
|
EBVALUE_OP_GET_PTR,
|
||||||
|
EBVALUE_OP_ADD,
|
||||||
|
EBVALUE_OP_SUB,
|
||||||
|
EBVALUE_OP_MUL,
|
||||||
|
EBVALUE_OP_DIV,
|
||||||
|
EBVALUE_OP_PARENTHESIS,
|
||||||
|
EBVALUE_OP_NEG,
|
||||||
|
EBVALUE_OP_NOT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node_t
|
||||||
|
{
|
||||||
|
BValue_t m_value;
|
||||||
|
struct Node_t *m_pLeftValue;
|
||||||
|
struct Node_t *m_pRightValue;
|
||||||
|
EBValueNodeOp m_eOp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScopeVariable_t
|
||||||
|
{
|
||||||
|
const char *szName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BValue_t ParseVar( CTokenParser *pParser )
|
||||||
{
|
{
|
||||||
const char *szToken = pParser->PeekToken();
|
const char *szToken = pParser->PeekToken();
|
||||||
|
|
||||||
return szToken;
|
if (V_isdigit(szToken[0]))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
return {EBVALUE_TYPE_INT_LITERAL, atoi(szToken)};
|
||||||
|
}
|
||||||
|
pParser->Continue();
|
||||||
|
return {EBVALUE_TYPE_VARIABLE, 0, szToken};
|
||||||
};
|
};
|
||||||
|
Node_t *ParseExpr( CTokenParser *pParser );
|
||||||
|
void ParseRValue( CTokenParser *pParser );
|
||||||
|
Node_t *ParsePrimary( CTokenParser *pParser )
|
||||||
|
{
|
||||||
|
Node_t *pNode;
|
||||||
|
if (pParser->IsToken("("))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
pNode = ParseExpr(pParser);
|
||||||
|
if (!pParser->IsToken(")"))
|
||||||
|
CompileErrorExpectedToken(pParser->m_pCurrentToken, ")");
|
||||||
|
pParser->Continue();
|
||||||
|
goto lvalue;
|
||||||
|
}
|
||||||
|
pNode = new Node_t();
|
||||||
|
pNode->m_eOp = EBVALUE_OP_VALUE;
|
||||||
|
pNode->m_value = ParseVar( pParser );
|
||||||
|
lvalue:
|
||||||
|
if (pParser->IsToken("="))
|
||||||
|
{
|
||||||
|
if (pNode->m_eOp == EBVALUE_OP_VALUE)
|
||||||
|
{
|
||||||
|
if ( pNode->m_value.m_eType == EBVALUE_TYPE_VARIABLE )
|
||||||
|
goto confirmedlvalue;
|
||||||
|
};
|
||||||
|
CompileErrorGotRValue(pParser->m_pCurrentToken);
|
||||||
|
confirmedlvalue:
|
||||||
|
pParser->Continue();
|
||||||
|
ParseRValue(pParser);
|
||||||
|
};
|
||||||
|
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
Node_t *ParseUnary( CTokenParser *pParser )
|
||||||
|
{
|
||||||
|
return ParsePrimary(pParser);
|
||||||
|
}
|
||||||
|
Node_t *ParseTerm( CTokenParser *pParser )
|
||||||
|
{
|
||||||
|
Node_t *pNode;
|
||||||
|
Node_t *pNewNode;
|
||||||
|
|
||||||
|
EBValueNodeOp eOp = EBVALUE_OP_NOTHING;
|
||||||
|
pNode = new Node_t();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pParser->IsToken("*"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
eOp = EBVALUE_OP_MUL;
|
||||||
|
}
|
||||||
|
else if (pParser->IsToken("/"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
eOp = EBVALUE_OP_DIV;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pNode->m_eOp = eOp;
|
||||||
|
if (pNode->m_pLeftValue == NULL)
|
||||||
|
pNode->m_pLeftValue = ParseUnary(pParser);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (eOp == EBVALUE_OP_NOTHING)
|
||||||
|
break;
|
||||||
|
eOp = EBVALUE_OP_NOTHING;
|
||||||
|
pNode->m_pRightValue = ParseUnary(pParser);
|
||||||
|
pNewNode = new Node_t();
|
||||||
|
pNewNode->m_pLeftValue = pNode;
|
||||||
|
pNode = pNewNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pNode->m_pRightValue == NULL)
|
||||||
|
{
|
||||||
|
pNewNode = pNode->m_pLeftValue;
|
||||||
|
delete pNode;
|
||||||
|
return pNewNode;
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node_t *ParseExpr( CTokenParser *pParser )
|
||||||
|
{
|
||||||
|
Node_t *pNode;
|
||||||
|
Node_t *pNewNode;
|
||||||
|
|
||||||
|
EBValueNodeOp eOp = EBVALUE_OP_NOTHING;
|
||||||
|
pNode = new Node_t();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pParser->IsToken("+"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
eOp = EBVALUE_OP_ADD;
|
||||||
|
}
|
||||||
|
else if (pParser->IsToken("-"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
eOp = EBVALUE_OP_SUB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pNode->m_eOp = eOp;
|
||||||
|
if (pNode->m_pLeftValue == NULL)
|
||||||
|
pNode->m_pLeftValue = ParseTerm(pParser);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (eOp == EBVALUE_OP_NOTHING)
|
||||||
|
break;
|
||||||
|
eOp = EBVALUE_OP_NOTHING;
|
||||||
|
pNode->m_pRightValue = ParseTerm(pParser);
|
||||||
|
pNewNode = new Node_t();
|
||||||
|
pNewNode->m_pLeftValue = pNode;
|
||||||
|
pNode = pNewNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pNode->m_pRightValue == NULL)
|
||||||
|
{
|
||||||
|
pNewNode = pNode->m_pLeftValue;
|
||||||
|
delete pNode;
|
||||||
|
return pNewNode;
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintExpr( Node_t *pNode )
|
||||||
|
{
|
||||||
|
if ( pNode->m_eOp == EBVALUE_OP_VALUE )
|
||||||
|
{
|
||||||
|
switch ( pNode->m_value.m_eType )
|
||||||
|
{
|
||||||
|
case EBVALUE_TYPE_INT_LITERAL:
|
||||||
|
V_printf("%i\n", pNode->m_value.m_iLiteral);
|
||||||
|
break;
|
||||||
|
case EBVALUE_TYPE_VARIABLE:
|
||||||
|
V_printf("%s\n", pNode->m_value.m_szVarName);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pNode->m_pLeftValue)
|
||||||
|
PrintExpr(pNode->m_pLeftValue);
|
||||||
|
if (pNode->m_pRightValue)
|
||||||
|
PrintExpr(pNode->m_pRightValue);
|
||||||
|
if (pNode->m_eOp == EBVALUE_OP_ADD)
|
||||||
|
V_printf("+\n");
|
||||||
|
if (pNode->m_eOp == EBVALUE_OP_SUB)
|
||||||
|
V_printf("-\n");
|
||||||
|
if (pNode->m_eOp == EBVALUE_OP_MUL)
|
||||||
|
V_printf("*\n");
|
||||||
|
if (pNode->m_eOp == EBVALUE_OP_DIV)
|
||||||
|
V_printf("/\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ParseRValue( CTokenParser *pParser )
|
void ParseRValue( CTokenParser *pParser )
|
||||||
{
|
{
|
||||||
if (pParser->PeekToken() == "(")
|
PrintExpr(ParseExpr( pParser ));
|
||||||
{
|
|
||||||
pParser->PeekToken();
|
|
||||||
ParseRValue(pParser)
|
|
||||||
}
|
|
||||||
BVar_t var = ParseVar( pParser );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseStatement( CTokenParser *pParser )
|
void ParseStatement( CTokenParser *pParser )
|
||||||
@@ -93,14 +283,65 @@ void ParseStatement( CTokenParser *pParser )
|
|||||||
V_printf(" ret\n");
|
V_printf(" ret\n");
|
||||||
pParser->Continue();
|
pParser->Continue();
|
||||||
}
|
}
|
||||||
|
else if (pParser->IsToken("extrn"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const char *szName = pParser->PeekToken();
|
||||||
|
pParser->Continue();
|
||||||
|
if (pParser->IsToken(","))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pParser->IsToken(";"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CompileErrorUnexpectedToken(pParser->m_pCurrentToken);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (pParser->IsToken("auto"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const char *szName = pParser->PeekToken();
|
||||||
|
pParser->Continue();
|
||||||
|
if (pParser->IsToken(","))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pParser->IsToken(";"))
|
||||||
|
{
|
||||||
|
pParser->Continue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CompileErrorUnexpectedToken(pParser->m_pCurrentToken);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ParseRValue(pParser);
|
||||||
|
if (!pParser->IsToken(";"))
|
||||||
|
CompileErrorExpectedToken(pParser->m_pCurrentToken, ";");
|
||||||
|
pParser->Continue();
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseGlobal( CTokenParser *pParser )
|
void ParseGlobal( CTokenParser *pParser )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pParser->IsEOF())
|
||||||
|
break;
|
||||||
const char *szObjectName = pParser->PeekToken();
|
const char *szObjectName = pParser->PeekToken();
|
||||||
pParser->Continue();
|
pParser->Continue();
|
||||||
V_printf("%s:\n", szObjectName);
|
|
||||||
|
|
||||||
if (pParser->IsToken("("))
|
if (pParser->IsToken("("))
|
||||||
{
|
{
|
||||||
@@ -108,6 +349,8 @@ void ParseGlobal( CTokenParser *pParser )
|
|||||||
if (!pParser->IsToken(")"))
|
if (!pParser->IsToken(")"))
|
||||||
CompileErrorExpectedToken(pParser->m_pCurrentToken, ")");
|
CompileErrorExpectedToken(pParser->m_pCurrentToken, ")");
|
||||||
pParser->Continue();
|
pParser->Continue();
|
||||||
|
g_pGenerator->DefineFunction(szObjectName);
|
||||||
|
|
||||||
if (!pParser->IsToken("{"))
|
if (!pParser->IsToken("{"))
|
||||||
CompileErrorExpectedToken(pParser->m_pCurrentToken, "{");
|
CompileErrorExpectedToken(pParser->m_pCurrentToken, "{");
|
||||||
pParser->Continue();
|
pParser->Continue();
|
||||||
@@ -121,6 +364,8 @@ void ParseGlobal( CTokenParser *pParser )
|
|||||||
{
|
{
|
||||||
CompileErrorExpectedToken(pParser->m_pCurrentToken, "(");
|
CompileErrorExpectedToken(pParser->m_pCurrentToken, "(");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
V_printf("%s\n", g_pGenerator->GetAssembly().GetString());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -135,6 +380,8 @@ int main( int argc, char **argv )
|
|||||||
const char *szFileContents = filesystem->ReadString(pFile);
|
const char *szFileContents = filesystem->ReadString(pFile);
|
||||||
filesystem->Close(pFile);
|
filesystem->Close(pFile);
|
||||||
|
|
||||||
|
g_pGenerator = (IBGenerator*)CreateInterface(B_GENERATOR_INTERFACE_VERSION, NULL);
|
||||||
|
|
||||||
|
|
||||||
CUtlVector<Token_t> tokens = Tokenize(szFileContents);
|
CUtlVector<Token_t> tokens = Tokenize(szFileContents);
|
||||||
CTokenParser parser;
|
CTokenParser parser;
|
||||||
|
|||||||
@@ -7,6 +7,61 @@ ADD_DEPENDENCY_BUILD_FILE(tier1, "../tier1/build.cpp")
|
|||||||
ADD_DEPENDENCY_BUILD_FILE(tier2, "../tier2/build.cpp")
|
ADD_DEPENDENCY_BUILD_FILE(tier2, "../tier2/build.cpp")
|
||||||
ADD_DEPENDENCY_BUILD_FILE(fs, "../stdfilesystems/build.cpp")
|
ADD_DEPENDENCY_BUILD_FILE(fs, "../stdfilesystems/build.cpp")
|
||||||
|
|
||||||
|
|
||||||
|
DECLARE_BUILD_STAGE(libbras)
|
||||||
|
{
|
||||||
|
CProject_t stProject = {};
|
||||||
|
LinkProject_t stLink = {};
|
||||||
|
CUtlString szBuiltFile = {};
|
||||||
|
|
||||||
|
stProject.m_szName = "bras";
|
||||||
|
stProject.files = {
|
||||||
|
"as/as.cpp",
|
||||||
|
};
|
||||||
|
stProject.includeDirectories = {
|
||||||
|
"../public"
|
||||||
|
};
|
||||||
|
|
||||||
|
stLink = ccompiler->Compile(&stProject);
|
||||||
|
stLink.linkType = ELINK_STATIC_LIBRARY;
|
||||||
|
stLink.libraryObjects = {
|
||||||
|
GET_PROJECT_LIBRARY(tier0, "tier0"),
|
||||||
|
GET_PROJECT_LIBRARY(tier1, "tier1"),
|
||||||
|
GET_PROJECT_LIBRARY(tier2, "tier2"),
|
||||||
|
};
|
||||||
|
szBuiltFile = linker->Link(&stLink);
|
||||||
|
ADD_OUTPUT_OBJECT("bras", szBuiltFile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_BUILD_STAGE(bras)
|
||||||
|
{
|
||||||
|
CProject_t stProject = {};
|
||||||
|
LinkProject_t stLink = {};
|
||||||
|
CUtlString szBuiltFile = {};
|
||||||
|
|
||||||
|
stProject.m_szName = "bras";
|
||||||
|
stProject.files = {
|
||||||
|
"as/main.cpp",
|
||||||
|
};
|
||||||
|
stProject.includeDirectories = {
|
||||||
|
"../public"
|
||||||
|
};
|
||||||
|
|
||||||
|
stLink = ccompiler->Compile(&stProject);
|
||||||
|
stLink.libraryObjects = {
|
||||||
|
GET_PROJECT_LIBRARY(libbras, "bras"),
|
||||||
|
GET_PROJECT_LIBRARY(tier0, "tier0"),
|
||||||
|
GET_PROJECT_LIBRARY(tier1, "tier1"),
|
||||||
|
GET_PROJECT_LIBRARY(tier2, "tier2"),
|
||||||
|
};
|
||||||
|
szBuiltFile = linker->Link(&stLink);
|
||||||
|
ADD_OUTPUT_OBJECT("bras", szBuiltFile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
DECLARE_BUILD_STAGE(brb)
|
DECLARE_BUILD_STAGE(brb)
|
||||||
{
|
{
|
||||||
CProject_t stProject = {};
|
CProject_t stProject = {};
|
||||||
@@ -15,7 +70,6 @@ DECLARE_BUILD_STAGE(brb)
|
|||||||
|
|
||||||
stProject.m_szName = "bc";
|
stProject.m_szName = "bc";
|
||||||
stProject.files = {
|
stProject.files = {
|
||||||
"brb/lexer.cpp",
|
|
||||||
"brb/main.cpp",
|
"brb/main.cpp",
|
||||||
};
|
};
|
||||||
stProject.includeDirectories = {
|
stProject.includeDirectories = {
|
||||||
@@ -24,6 +78,7 @@ DECLARE_BUILD_STAGE(brb)
|
|||||||
|
|
||||||
stLink = ccompiler->Compile(&stProject);
|
stLink = ccompiler->Compile(&stProject);
|
||||||
stLink.libraryObjects = {
|
stLink.libraryObjects = {
|
||||||
|
GET_PROJECT_LIBRARY(libbras, "bras"),
|
||||||
GET_PROJECT_LIBRARY(tier0, "tier0"),
|
GET_PROJECT_LIBRARY(tier0, "tier0"),
|
||||||
GET_PROJECT_LIBRARY(tier1, "tier1"),
|
GET_PROJECT_LIBRARY(tier1, "tier1"),
|
||||||
GET_PROJECT_LIBRARY(tier2, "tier2"),
|
GET_PROJECT_LIBRARY(tier2, "tier2"),
|
||||||
@@ -34,11 +89,12 @@ DECLARE_BUILD_STAGE(brb)
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_BUILD_STAGE(brb_install)
|
DECLARE_BUILD_STAGE(install)
|
||||||
{
|
{
|
||||||
CUtlString szBuildOutput = CUtlString("build/%s", Target_t::DefaultTarget().GetTriplet().GetString());
|
CUtlString szBuildOutput = CUtlString("build/%s", Target_t::DefaultTarget().GetTriplet().GetString());
|
||||||
filesystem2->MakeDirectory(szBuildOutput);
|
filesystem2->MakeDirectory(szBuildOutput);
|
||||||
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_OBJECT(brb, "bc"));
|
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_OBJECT(brb, "bc"));
|
||||||
|
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_OBJECT(bras, "bras"));
|
||||||
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_LIBRARY(tier0, "tier0"));
|
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_LIBRARY(tier0, "tier0"));
|
||||||
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_LIBRARY(filesystem_std, "fs"));
|
filesystem2->CopyFile(szBuildOutput, GET_PROJECT_LIBRARY(filesystem_std, "fs"));
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
26
asmrigs/libbr/math.s
Normal file
26
asmrigs/libbr/math.s
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
public min
|
||||||
|
min:
|
||||||
|
pop b
|
||||||
|
pop c
|
||||||
|
min a, b, c
|
||||||
|
ret
|
||||||
|
|
||||||
|
public max
|
||||||
|
max:
|
||||||
|
pop b
|
||||||
|
pop c
|
||||||
|
max a, b, c
|
||||||
|
ret
|
||||||
|
|
||||||
|
public abs
|
||||||
|
abs:
|
||||||
|
pop b
|
||||||
|
abs a, b, c
|
||||||
|
ret
|
||||||
|
|
||||||
|
public sign
|
||||||
|
sign:
|
||||||
|
pop b
|
||||||
|
sign a, b
|
||||||
|
ret
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
Brick Rigs B is a programming language made to work in the game Brick Rigs
|
|
||||||
|
|
||||||
1. The main issues of Brick Rigs
|
|
||||||
|
|
||||||
There are multiple limitations that are present in Brick Rigs:
|
|
||||||
1. Math Bricks are updated once per frame. It limits them to be one
|
|
||||||
time usage, which may cause some problems if you want to set the same
|
|
||||||
brick multiple times.
|
|
||||||
|
|
||||||
To solve this issue we've developed multiple targets:
|
|
||||||
1. Native Brick Rigs framed - allows to run code once per frame,
|
|
||||||
useful for missiles and custom built-logic.
|
|
||||||
2. Native Brick Rigs stacked - splits the code into multiple
|
|
||||||
parts, which allows stack to occur at a cost of a single frame.
|
|
||||||
3. Combat Advanced's virtual machine - it allows to run complex code by
|
|
||||||
using Combat Advanced's virtual machine
|
|
||||||
|
|
||||||
There are multiple extensions for native Brick Rigs
|
|
||||||
1. Combat Advanced's memory module
|
|
||||||
2. Combat Advanced's trigonometry functions
|
|
||||||
|
|
||||||
2. Syntaxis
|
|
||||||
|
|
||||||
It can be seen in B user's guide
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
Brick Rigs math vehicle object file specification v 1.0.
|
|
||||||
|
|
||||||
1. Terminology
|
|
||||||
"byte" must be 1 byte long (uint8_t in C)
|
|
||||||
"word" must be 2 bytes long (uint16_t in C)
|
|
||||||
"int" must be 4 bytes long (uint16_t in C)
|
|
||||||
|
|
||||||
2. Global header
|
|
||||||
|
|
||||||
First comes global header which has following structure:
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
byte magic[4];
|
|
||||||
byte architecture[2];
|
|
||||||
word symbols_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
Where:
|
|
||||||
magic must equal to 0x1 'B' 'M' 'O'
|
|
||||||
architecture is defined per implementation
|
|
||||||
symbols_number is the amount of symbols
|
|
||||||
|
|
||||||
3. Symbols
|
|
||||||
|
|
||||||
First comes the header:
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
byte type;
|
|
||||||
int name_offset;
|
|
||||||
byte name_lenght;
|
|
||||||
int data_offset;
|
|
||||||
byte data_lenght;
|
|
||||||
}
|
|
||||||
|
|
||||||
Where:
|
|
||||||
type is equal to 0x1 which defines function or 0x2 which defines variable
|
|
||||||
name_lenght is equal to the lenght of the name of the symbol + 1
|
|
||||||
data_lenght is equal to the data lenght of the symbol
|
|
||||||
|
|
||||||
After that comes the ASCII terminated by 0x0 set of lenght of name_lenght, which defined name of the symbol
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
main()
|
_tick()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
3
asmrigs/tests/001.s
Normal file
3
asmrigs/tests/001.s
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
public _tick
|
||||||
|
_tick:
|
||||||
|
ret
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
main()
|
_tick()
|
||||||
{
|
{
|
||||||
return 0;
|
extrn a;
|
||||||
|
a = 30;
|
||||||
}
|
}
|
||||||
|
|||||||
3
asmrigs/tests/002.s
Normal file
3
asmrigs/tests/002.s
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
public _tick
|
||||||
|
_tick:
|
||||||
|
ret
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
main()
|
_tick()
|
||||||
{
|
{
|
||||||
return 1 + 2 * 3;
|
extrn a;
|
||||||
|
a = 1 + 2 * 3 * ( 4 + 5 );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
extrn something;
|
||||||
auto a, b;
|
auto a, b;
|
||||||
a = 10;
|
a = 10;
|
||||||
b = a + 5;
|
b = a + 5;
|
||||||
|
|||||||
14
public/asmrigs/as.h
Normal file
14
public/asmrigs/as.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef ASMRIGS_AS_H
|
||||||
|
#define ASMRIGS_AS_H
|
||||||
|
|
||||||
|
#include "tier0/platform.h"
|
||||||
|
#include "tier1/utlbuffer.h"
|
||||||
|
|
||||||
|
struct AsOptions_t
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CUtlBuffer<uint8_t> Assemble( const char *szAssembly, AsOptions_t stOptions );
|
||||||
|
|
||||||
|
#endif
|
||||||
6
public/asmrigs/ld.h
Normal file
6
public/asmrigs/ld.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef ASMRIGS_LD_H
|
||||||
|
#define ASMRIGS_LD_H
|
||||||
|
|
||||||
|
#include "tier0/interface.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
55
public/asmrigs/tokenparser.h
Normal file
55
public/asmrigs/tokenparser.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef ASMRIGS_TOKEN_PARSER
|
||||||
|
#define ASMRIGS_TOKEN_PARSER
|
||||||
|
|
||||||
|
#include "tier2/tokenizer.h"
|
||||||
|
|
||||||
|
class CTokenParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool IsEOF();
|
||||||
|
const char *PeekToken();
|
||||||
|
bool IsToken( const char *szString );
|
||||||
|
const char *PeekStringLiteral();
|
||||||
|
bool Continue();
|
||||||
|
|
||||||
|
Token_t *m_pTokens;
|
||||||
|
Token_t *m_pTokensEnd;
|
||||||
|
Token_t *m_pCurrentToken;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char *CTokenParser::PeekToken()
|
||||||
|
{
|
||||||
|
if ( m_pCurrentToken->m_bIsQuoted )
|
||||||
|
return NULL;
|
||||||
|
return m_pCurrentToken->m_szValue;
|
||||||
|
}
|
||||||
|
inline bool CTokenParser::IsEOF()
|
||||||
|
{
|
||||||
|
if (m_pCurrentToken == m_pTokensEnd)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool CTokenParser::IsToken( const char *szString )
|
||||||
|
{
|
||||||
|
if ( !V_strcmp(szString, m_pCurrentToken->m_szValue))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char *CTokenParser::PeekStringLiteral()
|
||||||
|
{
|
||||||
|
if ( !m_pCurrentToken->m_bIsQuoted )
|
||||||
|
return NULL;
|
||||||
|
return m_pCurrentToken->m_szValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CTokenParser::Continue()
|
||||||
|
{
|
||||||
|
m_pCurrentToken++;
|
||||||
|
if ( m_pCurrentToken == m_pTokensEnd )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -76,10 +76,10 @@ CUtlBuffer<T>::CUtlBuffer( const CUtlBuffer<T>& buffer ) : m_nSize(buffer.m_nSiz
|
|||||||
// Constructor.
|
// Constructor.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
CUtlBuffer<T>::CUtlBuffer( const CUtlResizableBuffer<T>& buffer ) : m_nSize(buffer.m_nSize)
|
CUtlBuffer<T>::CUtlBuffer( const CUtlResizableBuffer<T>& buffer ) : m_nSize(buffer.GetSize())
|
||||||
{
|
{
|
||||||
m_pData = (T*)V_malloc(sizeof(T)*buffer.nSize);
|
m_pData = (T*)V_malloc(sizeof(T)*buffer.GetSize());
|
||||||
V_memcpy(m_pData,buffer.pData,sizeof(T)*buffer.nSize);
|
V_memcpy(m_pData,buffer.GetMemory(),sizeof(T)*buffer.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
Reference in New Issue
Block a user