#include "brb.h" #include "asmrigs/tokenparser.h" #include "tier0/commandline.h" #include "tier2/ifilesystem.h" IBGenerator *g_pGenerator; class CBGenerator: public IBGenerator { public: virtual void AddExternSymbol( const char *szName ) override; virtual void DefineFunction( const char *szName ) override; virtual CUtlString GetAssembly() override; CUtlVector m_externalSymbols; CUtlString m_szAssembly; }; EXPOSE_INTERFACE(CBGenerator, IBGenerator, B_GENERATOR_INTERFACE_VERSION); void CBGenerator::AddExternSymbol( const char *szName ) { m_externalSymbols.AppendTail(szName); } void CBGenerator::DefineFunction( const char *szName ) { m_szAssembly.AppendTail(CUtlString("public %s\n", szName)); m_szAssembly.AppendTail(CUtlString("%s:\n", szName)); } CUtlString CBGenerator::GetAssembly() { return m_szAssembly; } void CompileErrorExpectedToken( Token_t *pToken, const char *szToken ) { if (pToken->m_bIsQuoted) V_printf("%d:%d: expected %s but got string literal\n", pToken->m_iLine, pToken->m_iCharacter, szToken); else V_printf("%d:%d: expected %s but got %s\n", pToken->m_iLine, pToken->m_iCharacter, szToken, pToken->m_szValue.GetString()); exit(1); } void CompileErrorUnexpectedToken( Token_t *pToken ) { if (pToken->m_bIsQuoted) V_printf("%d:%d: unexpected string literal\n", pToken->m_iLine, pToken->m_iCharacter ); else V_printf("%d:%d: unexpected %s\n", pToken->m_iLine, pToken->m_iCharacter, pToken->m_szValue.GetString()); exit(1); } 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, }; 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(); 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 ) { PrintExpr(ParseExpr( pParser )); } void ParseStatement( CTokenParser *pParser ) { if (pParser->IsToken("return")) { pParser->Continue(); ParseRValue( pParser ); if (!pParser->IsToken(";")) CompileErrorExpectedToken(pParser->m_pCurrentToken, ";"); V_printf(" ret\n"); 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 ) { for (;;) { if (pParser->IsEOF()) break; const char *szObjectName = pParser->PeekToken(); pParser->Continue(); if (pParser->IsToken("(")) { pParser->Continue(); if (!pParser->IsToken(")")) CompileErrorExpectedToken(pParser->m_pCurrentToken, ")"); pParser->Continue(); g_pGenerator->DefineFunction(szObjectName); if (!pParser->IsToken("{")) CompileErrorExpectedToken(pParser->m_pCurrentToken, "{"); pParser->Continue(); while (!pParser->IsToken("}")) { ParseStatement( pParser ); } pParser->Continue(); } else { CompileErrorExpectedToken(pParser->m_pCurrentToken, "("); } } V_printf("%s\n", g_pGenerator->GetAssembly().GetString()); }; 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); g_pGenerator = (IBGenerator*)CreateInterface(B_GENERATOR_INTERFACE_VERSION, NULL); CUtlVector tokens = Tokenize(szFileContents); CTokenParser parser; parser.m_pTokens = tokens.GetData(); parser.m_pTokensEnd = tokens.GetData()+tokens.GetSize(); parser.m_pCurrentToken = tokens.GetData()-1; parser.Continue(); ParseGlobal(&parser); V_free((void*)szFileContents); }