HyperDbg/hyperdbg/script-engine/ScriptEngine.c

1077 lines
27 KiB
C
Raw Normal View History

2020-10-22 18:56:58 +03:30
/**
* @file ScriptEngine.c
* @author M.H. Gholamrezei (gholamrezaei.mh@gmail.com)
* @brief Script engine parser and codegen
* @details
* @version 0.1
* @date 2020-10-22
*
* @copyright This project is released under the GNU Public License v3.
*
*/
2020-10-20 19:35:15 +03:30
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
2020-12-02 02:32:49 +03:30
#include "globals.h"
2020-12-01 22:26:46 +03:30
#include "common.h"
2020-11-04 17:30:33 +03:30
#include "parse_table.h"
2020-10-20 19:35:15 +03:30
#include "ScriptEngine.h"
2020-12-02 15:52:49 +03:30
#include "ScriptEngineCommonDefinitions.h"
2020-10-24 14:36:07 +03:30
#include "string.h"
2021-03-03 16:53:19 +03:30
2021-04-11 18:27:23 +04:30
//#define _SCRIPT_ENGINE_DBG_EN
2020-10-20 19:35:15 +03:30
/**
*
*
*/
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER
ScriptEngineParse(char * str)
2020-10-20 19:35:15 +03:30
{
TOKEN_LIST Stack = NewTokenList();
TOKEN_LIST LALRInputTokens;
2021-04-11 18:27:23 +04:30
TOKEN_LIST MatchedStack = NewTokenList();
PSYMBOL_BUFFER CodeBuffer = NewSymbolBuffer();
2020-10-20 19:35:15 +03:30
2021-03-22 18:19:39 +04:30
static FirstCall = 1;
2021-03-03 16:53:19 +03:30
if (FirstCall)
{
2021-03-22 18:19:39 +04:30
IdTable = NewTokenList();
2021-03-03 16:53:19 +03:30
FirstCall = 0;
}
2020-10-20 19:35:15 +03:30
TOKEN CurrentIn;
TOKEN TopToken;
2020-12-02 02:32:49 +03:30
2021-03-22 18:19:39 +04:30
int NonTerminalId;
int TerminalId;
int RuleId;
2020-10-20 19:35:15 +03:30
char c;
2020-10-24 14:36:07 +03:30
2020-12-03 18:02:49 +03:30
//
2021-03-22 18:19:39 +04:30
// Initialize Scanner
//
InputIdx = 0;
CurrentLine = 0;
2020-12-03 18:02:49 +03:30
CurrentLineIdx = 0;
2021-03-22 18:19:39 +04:30
2020-10-20 19:35:15 +03:30
//
// End of File Token
//
TOKEN EndToken = NewToken();
EndToken->Type = END_OF_STACK;
strcpy(EndToken->Value, "$");
//
// Start Token
//
TOKEN StartToken = NewToken();
strcpy(StartToken->Value, START_VARIABLE);
StartToken->Type = NON_TERMINAL;
Push(Stack, EndToken);
Push(Stack, StartToken);
c = sgetc(str);
2020-10-22 18:08:20 +03:30
2020-10-20 19:35:15 +03:30
CurrentIn = Scan(str, &c);
2020-10-24 14:36:07 +03:30
if (CurrentIn->Type == UNKNOWN)
{
2021-03-22 18:19:39 +04:30
char * Message = HandleError(UNKOWN_TOKEN, str);
2020-12-03 18:02:49 +03:30
CodeBuffer->Message = Message;
2020-12-02 02:32:49 +03:30
2020-10-24 14:36:07 +03:30
RemoveTokenList(Stack);
RemoveTokenList(MatchedStack);
2020-11-29 23:09:39 +03:30
RemoveToken(CurrentIn);
2020-10-24 14:36:07 +03:30
return CodeBuffer;
}
2020-10-20 19:35:15 +03:30
do
{
TopToken = Pop(Stack);
#ifdef _SCRIPT_ENGINE_DBG_EN
printf("\nTop Token :\n");
PrintToken(TopToken);
printf("\nCurrent Input :\n");
PrintToken(CurrentIn);
printf("\n");
#endif
2020-12-02 02:32:49 +03:30
2020-10-20 19:35:15 +03:30
if (TopToken->Type == NON_TERMINAL)
{
if (TopToken->Value == "BOOLEAN_EXPRESSION")
2020-10-20 19:35:15 +03:30
{
LALRInputTokens = NewTokenList();
Push(LALRInputTokens, CurrentIn);
2021-04-11 18:27:23 +04:30
int OpenParanthesesCount = 1;
if (!strcmp(CurrentIn->Value, "("))
{
OpenParanthesesCount++;
}
2021-04-11 18:27:23 +04:30
while (1)
{
CurrentIn = Scan(str, &c);
2021-04-11 18:27:23 +04:30
if (!strcmp(CurrentIn->Value, "("))
{
OpenParanthesesCount++;
Push(LALRInputTokens, CurrentIn);
}
else if (!strcmp(CurrentIn->Value, ")"))
{
OpenParanthesesCount--;
if (OpenParanthesesCount <= 0)
{
break;
}
else
{
Push(LALRInputTokens, CurrentIn);
}
}
else
{
Push(LALRInputTokens, CurrentIn);
}
}
Push(LALRInputTokens, EndToken);
2021-04-11 18:27:23 +04:30
char * Message = ScriptEngineBooleanExpresssionParse(LALRInputTokens, MatchedStack, CodeBuffer, str);
if (Message != NULL)
{
CodeBuffer->Message = Message;
2021-04-11 18:27:23 +04:30
RemoveToken(StartToken);
RemoveToken(EndToken);
RemoveTokenList(MatchedStack);
RemoveToken(CurrentIn);
return CodeBuffer;
}
2021-04-11 18:27:23 +04:30
CurrentIn = Scan(str, &c);
TopToken = Pop(Stack);
2020-10-20 19:35:15 +03:30
}
else
2020-10-20 19:35:15 +03:30
{
NonTerminalId = GetNonTerminalId(TopToken);
if (NonTerminalId == INVALID)
{
2021-04-11 18:27:23 +04:30
char * Message = HandleError(SYNTAX_ERROR, str);
CodeBuffer->Message = Message;
2020-12-02 02:32:49 +03:30
RemoveToken(StartToken);
RemoveToken(EndToken);
RemoveTokenList(MatchedStack);
RemoveToken(CurrentIn);
return CodeBuffer;
}
TerminalId = GetTerminalId(CurrentIn);
if (TerminalId == INVALID)
{
2021-04-11 18:27:23 +04:30
char * Message = HandleError(SYNTAX_ERROR, str);
CodeBuffer->Message = Message;
RemoveToken(StartToken);
RemoveToken(EndToken);
RemoveTokenList(MatchedStack);
RemoveToken(CurrentIn);
return CodeBuffer;
}
2021-02-25 23:36:27 +03:30
RuleId = ParseTable[NonTerminalId][TerminalId];
if (RuleId == INVALID)
{
2021-04-11 18:27:23 +04:30
char * Message = HandleError(SYNTAX_ERROR, str);
CodeBuffer->Message = Message;
2020-12-02 02:32:49 +03:30
RemoveToken(StartToken);
RemoveToken(EndToken);
RemoveTokenList(MatchedStack);
RemoveToken(CurrentIn);
return CodeBuffer;
}
2020-10-20 19:35:15 +03:30
//
// Push RHS Reversely into stack
//
for (int i = RhsSize[RuleId] - 1; i >= 0; i--)
{
TOKEN Token = &Rhs[RuleId][i];
2020-10-20 19:35:15 +03:30
if (Token->Type == EPSILON)
break;
Push(Stack, Token);
}
2020-10-20 19:35:15 +03:30
}
}
else if (TopToken->Type == SEMANTIC_RULE)
{
if (!strcmp(TopToken->Value, "@PUSH"))
{
TopToken = Pop(Stack);
Push(MatchedStack, CurrentIn);
2020-11-29 23:09:39 +03:30
2020-10-20 19:35:15 +03:30
CurrentIn = Scan(str, &c);
2020-11-29 23:09:39 +03:30
2020-10-24 14:36:07 +03:30
if (CurrentIn->Type == UNKNOWN)
{
2021-03-22 18:19:39 +04:30
char * Message = HandleError(UNKOWN_TOKEN, str);
2020-12-03 18:02:49 +03:30
CodeBuffer->Message = Message;
2020-12-02 02:32:49 +03:30
2020-11-29 23:09:39 +03:30
RemoveToken(StartToken);
RemoveToken(EndToken);
2020-12-01 22:26:46 +03:30
RemoveTokenList(MatchedStack);
2020-11-29 23:09:39 +03:30
RemoveToken(CurrentIn);
2020-10-24 14:36:07 +03:30
return CodeBuffer;
}
2020-10-20 19:35:15 +03:30
// char t = getchar();
}
else
{
CodeGen(MatchedStack, CodeBuffer, TopToken);
}
}
else
{
if (!IsEqual(TopToken, CurrentIn))
{
2021-03-22 18:19:39 +04:30
char * Message = HandleError(SYNTAX_ERROR, str);
2021-02-25 19:09:13 +03:30
CodeBuffer->Message = Message;
2020-12-02 02:32:49 +03:30
2020-11-29 23:09:39 +03:30
RemoveToken(StartToken);
RemoveToken(EndToken);
2020-12-01 22:26:46 +03:30
RemoveTokenList(MatchedStack);
2020-11-29 23:09:39 +03:30
RemoveToken(CurrentIn);
2020-10-24 14:36:07 +03:30
return CodeBuffer;
2020-10-20 19:35:15 +03:30
}
else
{
2020-10-24 12:56:53 +03:30
RemoveToken(CurrentIn);
2020-10-20 19:35:15 +03:30
CurrentIn = Scan(str, &c);
2020-11-29 23:09:39 +03:30
2020-12-03 18:02:49 +03:30
if (CurrentIn->Type == UNKNOWN)
{
2021-03-22 18:19:39 +04:30
char * Message = HandleError(SYNTAX_ERROR, str);
2020-12-03 18:02:49 +03:30
CodeBuffer->Message = Message;
RemoveToken(StartToken);
RemoveToken(EndToken);
RemoveTokenList(MatchedStack);
RemoveToken(CurrentIn);
return CodeBuffer;
}
2021-03-22 18:19:39 +04:30
/* printf("\nCurrent Input :\n");
2020-10-20 19:35:15 +03:30
PrintToken(CurrentIn);
2020-12-03 18:02:49 +03:30
printf("\n");*/
2020-10-20 19:35:15 +03:30
#ifdef _SCRIPT_ENGINE_DBG_EN
printf("matched...\n");
#endif
}
}
#ifdef _SCRIPT_ENGINE_DBG_EN
2021-04-10 19:29:21 +04:30
printf("Stack: \n");
2021-03-22 18:19:39 +04:30
PrintTokenList(Stack);
printf("\n");
2020-10-20 19:35:15 +03:30
#endif
2021-03-22 18:19:39 +04:30
} while (TopToken->Type != END_OF_STACK);
2020-10-20 19:35:15 +03:30
2021-03-22 18:19:39 +04:30
RemoveTokenList(Stack);
2021-04-10 19:29:21 +04:30
//RemoveTokenList(LALRInputTokens);
2021-03-22 18:19:39 +04:30
RemoveTokenList(MatchedStack);
RemoveToken(StartToken);
RemoveToken(EndToken);
RemoveToken(CurrentIn);
return CodeBuffer;
}
2020-10-20 19:35:15 +03:30
2021-04-11 18:27:23 +04:30
void
CodeGen(TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, TOKEN Operator)
2020-10-20 19:35:15 +03:30
{
TOKEN Op0;
TOKEN Op1;
TOKEN Temp;
PSYMBOL OperatorSymbol;
PSYMBOL Op0Symbol;
PSYMBOL Op1Symbol;
PSYMBOL TempSymbol;
OperatorSymbol = ToSymbol(Operator);
if (!strcmp(Operator->Value, "@MOV"))
{
2021-02-12 03:12:01 +03:30
PushSymbol(CodeBuffer, OperatorSymbol);
2021-03-22 18:19:39 +04:30
Op0 = Pop(MatchedStack);
2021-02-12 03:12:01 +03:30
Op0Symbol = ToSymbol(Op0);
PushSymbol(CodeBuffer, Op0Symbol);
RemoveSymbol(Op0Symbol);
2021-03-22 18:19:39 +04:30
Op1 = Pop(MatchedStack);
2020-10-20 19:35:15 +03:30
Op1Symbol = ToSymbol(Op1);
PushSymbol(CodeBuffer, Op1Symbol);
2021-02-12 03:12:01 +03:30
RemoveSymbol(Op1Symbol);
2020-10-20 19:35:15 +03:30
2021-03-22 18:19:39 +04:30
/* printf("%s\t%s,\t%s\n", Operator->Value, Op1->Value, Op0->Value);
2020-12-03 18:02:49 +03:30
printf("_____________\n");*/
2020-10-20 19:35:15 +03:30
2020-10-24 14:36:07 +03:30
//
2020-10-20 19:35:15 +03:30
// Free the operand if it is a temp value
2020-10-24 14:36:07 +03:30
//
2020-10-20 19:35:15 +03:30
FreeTemp(Op0);
FreeTemp(Op1);
}
2020-12-02 02:44:37 +03:30
else if (IsType2Func(Operator))
{
2021-02-12 03:12:01 +03:30
PushSymbol(CodeBuffer, OperatorSymbol);
2021-03-22 18:19:39 +04:30
Op0 = Pop(MatchedStack);
2021-02-12 03:12:01 +03:30
Op0Symbol = ToSymbol(Op0);
PushSymbol(CodeBuffer, Op0Symbol);
RemoveSymbol(Op0Symbol);
2021-03-22 18:19:39 +04:30
/* printf("%s\t%s\n", Operator->Value, Op0->Value);
2020-12-03 18:02:49 +03:30
printf("_____________\n");*/
2020-12-02 02:44:37 +03:30
}
else if (IsType1Func(Operator))
{
2021-02-12 03:12:01 +03:30
PushSymbol(CodeBuffer, OperatorSymbol);
2021-03-22 18:19:39 +04:30
Op0 = Pop(MatchedStack);
2021-02-12 03:12:01 +03:30
Op0Symbol = ToSymbol(Op0);
PushSymbol(CodeBuffer, Op0Symbol);
RemoveSymbol(Op0Symbol);
2020-12-02 02:44:37 +03:30
Temp = NewTemp();
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp);
PushSymbol(CodeBuffer, TempSymbol);
2021-02-12 03:12:01 +03:30
RemoveSymbol(TempSymbol);
2021-03-22 18:19:39 +04:30
/* printf("%s\t%s,\t%s\n", Operator->Value, Temp->Value, Op0->Value);
2020-12-03 18:02:49 +03:30
printf("_____________\n");*/
2020-12-03 20:54:33 +03:30
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
2021-02-12 03:12:01 +03:30
}
else if (IsType4Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER TempStack = NewSymbolBuffer();
UINT32 OperandCount = 0;
2021-02-12 03:12:01 +03:30
do
{
Op1 = Pop(MatchedStack);
if (Op1->Type != SEMANTIC_RULE)
{
Op1Symbol = ToSymbol(Op1);
PushSymbol(TempStack, Op1Symbol);
RemoveSymbol(Op1Symbol);
FreeTemp(Op1);
OperandCount++;
}
2021-03-22 18:19:39 +04:30
} while (!(Op1->Type == SEMANTIC_RULE && !strcmp(Op1->Value, "@VARGSTART")));
2021-02-12 03:12:01 +03:30
2021-03-22 18:19:39 +04:30
Op0 = Pop(MatchedStack);
2021-02-12 03:12:01 +03:30
Op0Symbol = ToSymbol(Op0);
PushSymbol(CodeBuffer, Op0Symbol);
RemoveSymbol(Op0Symbol);
PSYMBOL OperandCountSymbol = NewSymbol();
2021-03-22 18:19:39 +04:30
OperandCountSymbol->Type = SYMBOL_VARIABLE_COUNT_TYPE;
OperandCountSymbol->Value = OperandCount;
2021-02-12 03:12:01 +03:30
PushSymbol(CodeBuffer, OperandCountSymbol);
RemoveSymbol(OperandCountSymbol);
PSYMBOL Symbol;
2021-03-22 18:19:39 +04:30
for (int i = TempStack->Pointer - 1; i >= 0; i--)
2021-02-12 03:12:01 +03:30
{
Symbol = TempStack->Head + i;
PushSymbol(CodeBuffer, Symbol);
}
RemoveSymbolBuffer(TempStack);
FreeTemp(Op0);
2020-12-02 02:44:37 +03:30
}
else if (IsType5Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
}
2020-12-02 03:20:34 +03:30
else if (IsNaiveOperator(Operator))
2020-10-20 19:35:15 +03:30
{
2021-02-12 03:12:01 +03:30
PushSymbol(CodeBuffer, OperatorSymbol);
2021-03-22 18:19:39 +04:30
Op0 = Pop(MatchedStack);
2021-02-12 03:12:01 +03:30
Op0Symbol = ToSymbol(Op0);
PushSymbol(CodeBuffer, Op0Symbol);
RemoveSymbol(Op0Symbol);
2021-03-22 18:19:39 +04:30
Op1 = Pop(MatchedStack);
2020-10-20 19:35:15 +03:30
Op1Symbol = ToSymbol(Op1);
PushSymbol(CodeBuffer, Op1Symbol);
2021-02-12 03:12:01 +03:30
RemoveSymbol(Op1Symbol);
2020-10-20 19:35:15 +03:30
Temp = NewTemp();
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp);
PushSymbol(CodeBuffer, TempSymbol);
2021-02-12 03:12:01 +03:30
RemoveSymbol(TempSymbol);
2021-03-22 18:19:39 +04:30
/* printf("%s\t%s,\t%s,\t%s\n", Operator->Value, Temp->Value, Op0->Value, Op1->Value);
2020-12-03 18:02:49 +03:30
printf("_____________\n");*/
2020-10-20 19:35:15 +03:30
2020-12-03 20:54:33 +03:30
//
2020-10-20 19:35:15 +03:30
// Free the operand if it is a temp value
2020-12-03 20:54:33 +03:30
//
2020-10-20 19:35:15 +03:30
FreeTemp(Op0);
FreeTemp(Op1);
2021-02-12 03:12:01 +03:30
}
2021-03-22 18:19:39 +04:30
else if (!strcmp(Operator->Value, "@VARGSTART"))
2021-02-12 03:12:01 +03:30
{
2021-03-22 18:19:39 +04:30
TOKEN OperatorCopy = NewToken();
2021-02-12 03:12:01 +03:30
OperatorCopy->Value = malloc(strlen(Operator->Value) + 1);
strcpy(OperatorCopy->Value, Operator->Value);
OperatorCopy->Type = Operator->Type;
Push(MatchedStack, OperatorCopy);
2020-12-02 03:20:34 +03:30
}
2021-04-11 18:27:23 +04:30
else if (!strcmp(Operator->Value, "@JZ"))
{
UINT64 CurrentPointer = CodeBuffer->Pointer;
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0);
PushSymbol(CodeBuffer, Op0Symbol);
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JumpAddressSymbol);
RemoveSymbol(JumpAddressSymbol);
TOKEN CurrentAddressToken = NewToken();
CurrentAddressToken->Type = DECIMAL;
char * str = malloc(16);
sprintf(str, "%llu", CurrentPointer);
CurrentAddressToken->Value = str;
Push(MatchedStack, CurrentAddressToken);
FreeTemp(Op0);
}
else if (!strcmp(Operator->Value, "@JZCOMPLETED"))
{
UINT64 CurrentPointer = CodeBuffer->Pointer;
TOKEN JumpSemanticAddressToken = Pop(MatchedStack);
UINT64 JumpSemanticAddress = DecimalToInt(JumpSemanticAddressToken->Value);
PSYMBOL JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpSemanticAddress + 2);
JumpAddressSymbol->Value = CurrentPointer;
PrintSymbolBuffer(CodeBuffer);
printf("\n");
}
2021-03-22 18:19:39 +04:30
2020-12-02 03:20:34 +03:30
else
{
2021-02-12 03:12:01 +03:30
printf("Internal Error: Unhandled semantic ruls.\n");
2020-12-02 02:44:37 +03:30
}
2021-02-12 03:12:01 +03:30
RemoveSymbol(OperatorSymbol);
2020-11-29 23:09:39 +03:30
return;
2020-10-20 19:35:15 +03:30
}
/**
*
*
*/
2021-04-11 18:27:23 +04:30
char *
ScriptEngineBooleanExpresssionParse(
TOKEN_LIST InputTokens,
TOKEN_LIST MatchedStack,
PSYMBOL_BUFFER CodeBuffer,
char * str)
{
TOKEN_LIST Stack = NewTokenList();
2021-04-11 18:27:23 +04:30
TOKEN State = NewToken();
State->Type = DECIMAL;
State->Value = malloc(strlen("0") + 1);
strcpy(State->Value, "0");
2021-04-11 18:27:23 +04:30
Push(Stack, State);
printf("----------------------------------------\n");
PrintTokenList(InputTokens);
printf("----------------------------------------\n");
TOKEN CurrentIn;
TOKEN TopToken;
TOKEN Lhs;
TOKEN Temp;
2021-04-11 18:27:23 +04:30
TOKEN Operand = NewToken();
TOKEN SemanticRule;
2021-04-11 18:27:23 +04:30
int Action = INVALID;
int StateId = 0;
int Goto = 0;
int InputPointer = 0;
2021-04-11 18:27:23 +04:30
int RhsSize = 0;
CurrentIn = InputTokens->Head[InputPointer++];
while (1)
{
2021-04-11 18:27:23 +04:30
TopToken = Top(Stack);
int TerminalId = LalrGetTerminalId(CurrentIn);
2021-04-11 18:27:23 +04:30
StateId = DecimalToSignedInt(TopToken->Value);
if (StateId == INVALID)
{
return;
}
Action = LalrActionTable[StateId][TerminalId];
2021-04-11 18:27:23 +04:30
#ifdef _SCRIPT_ENGINE_DBG_EN
printf("Stack :\n");
PrintTokenList(Stack);
printf("Action : %d\n", Action);
#endif
if (Action == LALR_ACCEPT)
{
2021-04-11 18:27:23 +04:30
printf("Matched Stack : \n");
PrintTokenList(MatchedStack);
return NULL;
}
if (Action == INVALID)
{
2021-04-11 18:27:23 +04:30
char * Message = HandleError(UNKOWN_TOKEN, str);
CodeBuffer->Message = Message;
return Message;
}
2021-04-11 18:27:23 +04:30
if (Action > 0) // Shift
{
StateId = Action;
Push(Stack, CurrentIn);
2021-04-11 18:27:23 +04:30
State = NewToken();
State->Type = DECIMAL;
State->Value = malloc(4);
sprintf(State->Value, "%d", StateId);
Push(Stack, State);
2021-04-11 18:27:23 +04:30
CurrentIn = InputTokens->Head[InputPointer++];
}
else if (Action < 0) // Reduce
{
2021-04-11 18:27:23 +04:30
StateId = -Action;
Lhs = &LalrLhs[StateId - 1];
RhsSize = LalrGetRhsSize(StateId - 1);
SemanticRule = &LalrSemanticRules[StateId - 1];
for (int i = 0; i < 2 * RhsSize; i++)
{
Temp = Pop(Stack);
2021-04-11 18:27:23 +04:30
if (SemanticRule->Type == SEMANTIC_RULE && !strcmp(SemanticRule->Value, "@PUSH"))
{
if (LalrIsOperandType(Temp))
{
if (Operand->Type == UNKNOWN)
{
RemoveToken(Operand);
}
Operand = Temp;
}
}
}
2021-04-11 18:27:23 +04:30
if (SemanticRule->Type == SEMANTIC_RULE)
{
if (!strcmp(SemanticRule->Value, "@PUSH"))
{
Push(MatchedStack, Operand);
2021-04-11 23:31:36 +04:30
2021-04-11 18:27:23 +04:30
}
else
{
2021-04-11 23:31:36 +04:30
CodeGen(MatchedStack, CodeBuffer, SemanticRule);
2021-04-11 18:27:23 +04:30
}
}
Temp = Top(Stack);
StateId = DecimalToSignedInt(Temp->Value);
Goto = LalrGotoTable[StateId][LalrGetNonTerminalId(Lhs)];
State = NewToken();
State->Type = DECIMAL;
State->Value = malloc(4);
sprintf(State->Value, "%d", Goto);
2021-04-11 18:27:23 +04:30
Push(Stack, Lhs);
Push(Stack, State);
}
}
2021-04-11 18:27:23 +04:30
return NULL;
}
2020-10-20 19:35:15 +03:30
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
PSYMBOL
NewSymbol(void)
2020-10-20 19:35:15 +03:30
{
PSYMBOL Symbol;
2021-03-22 18:19:39 +04:30
Symbol = (PSYMBOL)malloc(sizeof(*Symbol));
2020-10-20 19:35:15 +03:30
Symbol->Value = 0;
2021-03-22 18:19:39 +04:30
Symbol->Type = 0;
2020-10-20 19:35:15 +03:30
return Symbol;
}
2021-03-22 18:19:39 +04:30
PSYMBOL
NewStringSymbol(char * value)
2020-12-03 20:54:33 +03:30
{
PSYMBOL Symbol;
2021-03-22 18:19:39 +04:30
int BufferSize = (sizeof(unsigned long long) + (strlen(value))) / sizeof(SYMBOL) + 1;
Symbol = (unsigned long long)malloc(BufferSize * sizeof(SYMBOL));
2020-12-03 20:54:33 +03:30
strcpy(&Symbol->Value, value);
SetType(&Symbol->Type, SYMBOL_STRING_TYPE);
return Symbol;
}
2021-03-22 18:19:39 +04:30
unsigned int
GetStringSymbolSize(PSYMBOL Symbol)
2020-12-03 21:21:35 +03:30
{
2021-01-16 15:16:32 +03:30
int Temp = (sizeof(unsigned long long) + (strlen(&Symbol->Value))) / sizeof(SYMBOL) + 1;
2020-12-03 21:21:35 +03:30
return Temp;
}
2020-10-20 19:35:15 +03:30
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
void
RemoveSymbol(PSYMBOL Symbol)
2020-10-20 19:35:15 +03:30
{
free(Symbol);
return;
}
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
void
PrintSymbol(PSYMBOL Symbol)
2020-10-20 19:35:15 +03:30
{
2020-12-03 21:21:35 +03:30
if (Symbol->Type == SYMBOL_STRING_TYPE)
{
printf("Type:%llx, Value:%s\n", Symbol->Type, &Symbol->Value);
}
else
{
printf("Type:%llx, Value:0x%llx\n", Symbol->Type, Symbol->Value);
}
2020-10-20 19:35:15 +03:30
}
2021-03-22 18:19:39 +04:30
PSYMBOL
ToSymbol(TOKEN Token)
2020-10-20 19:35:15 +03:30
{
PSYMBOL Symbol = NewSymbol();
switch (Token->Type)
{
case ID:
2021-03-03 16:53:19 +03:30
Symbol->Value = GetIdentifierVal(Token);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_ID_TYPE);
return Symbol;
case DECIMAL:
Symbol->Value = DecimalToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
case HEX:
Symbol->Value = HexToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
case OCTAL:
Symbol->Value = OctalToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
case BINARY:
Symbol->Value = BinaryToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
case REGISTER:
2020-12-03 20:54:33 +03:30
Symbol->Value = RegisterToInt(Token->Value);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_REGISTER_TYPE);
return Symbol;
case PSEUDO_REGISTER:
2020-12-03 20:54:33 +03:30
Symbol->Value = PseudoRegToInt(Token->Value);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_PSEUDO_REG_TYPE);
return Symbol;
case SEMANTIC_RULE:
2021-03-22 18:19:39 +04:30
Symbol->Value = SemanticRuleToInt(Token->Value);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_SEMANTIC_RULE_TYPE);
return Symbol;
case TEMP:
2021-03-22 18:19:39 +04:30
Symbol->Value = DecimalToInt(Token->Value);
2020-12-02 18:11:03 +03:30
SetType(&Symbol->Type, SYMBOL_TEMP_TYPE);
2020-10-20 19:35:15 +03:30
return Symbol;
2020-12-03 20:54:33 +03:30
case STRING:
RemoveSymbol(Symbol);
return NewStringSymbol(Token->Value);
2020-10-20 19:35:15 +03:30
default:
// Raise Error
2021-03-22 18:19:39 +04:30
printf("Error in Converting Token with type %d to Symbol!\n", Token->Type);
2020-10-20 19:35:15 +03:30
}
}
2020-12-02 02:32:49 +03:30
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER
NewSymbolBuffer(void)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
PSYMBOL_BUFFER SymbolBuffer;
2021-03-22 18:19:39 +04:30
SymbolBuffer = (PSYMBOL_BUFFER)malloc(sizeof(*SymbolBuffer));
2020-12-02 02:32:49 +03:30
SymbolBuffer->Pointer = 0;
2021-03-22 18:19:39 +04:30
SymbolBuffer->Size = SYMBOL_BUFFER_INIT_SIZE;
SymbolBuffer->Head = (PSYMBOL)malloc(SymbolBuffer->Size * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
SymbolBuffer->Message = NULL;
return SymbolBuffer;
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
void
RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer)
2020-10-20 19:35:15 +03:30
{
2021-03-02 02:05:59 -08:00
// PrintSymbolBuffer(SymbolBuffer);
2020-12-02 02:32:49 +03:30
free(SymbolBuffer->Message);
free(SymbolBuffer->Head);
free(SymbolBuffer);
return;
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER
PushSymbol(PSYMBOL_BUFFER SymbolBuffer, const PSYMBOL Symbol)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
//
// Calculate address to write new token
//
2021-03-22 18:19:39 +04:30
uintptr_t Head = (uintptr_t)SymbolBuffer->Head;
uintptr_t Pointer = (uintptr_t)SymbolBuffer->Pointer;
PSYMBOL WriteAddr = (PSYMBOL)(Head + Pointer * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
2020-12-03 20:54:33 +03:30
if (Symbol->Type == SYMBOL_STRING_TYPE)
2021-03-22 18:19:39 +04:30
{
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Update Pointer
//
2021-01-16 15:16:32 +03:30
SymbolBuffer->Pointer += GetStringSymbolSize(Symbol);
2020-12-03 20:54:33 +03:30
//
// Handle Overflow
//
2021-03-02 02:48:41 +03:30
if (SymbolBuffer->Pointer >= SymbolBuffer->Size - 1)
2020-12-03 20:54:33 +03:30
{
2021-03-02 02:48:41 +03:30
//
// Calculate new size for the symbol B
//
int NewSize = SymbolBuffer->Size;
do
{
2021-03-22 18:19:39 +04:30
NewSize *= 2;
2021-03-11 18:27:29 +03:30
} while (NewSize <= SymbolBuffer->Pointer);
2021-03-02 02:48:41 +03:30
2020-12-03 20:54:33 +03:30
//
// Allocate a new buffer for string list with doubled length
//
2021-03-02 02:48:41 +03:30
PSYMBOL NewHead = (PSYMBOL)malloc(NewSize * sizeof(SYMBOL));
2020-12-03 20:54:33 +03:30
//
2021-03-02 02:48:41 +03:30
// Copy old buffer to new buffer
2020-12-03 20:54:33 +03:30
//
memcpy(NewHead, SymbolBuffer->Head, SymbolBuffer->Size * sizeof(SYMBOL));
//
2021-03-02 02:48:41 +03:30
// Free old buffer
2020-12-03 20:54:33 +03:30
//
free(SymbolBuffer->Head);
//
// Upadate Head and size of SymbolBuffer
//
2021-03-02 02:48:41 +03:30
SymbolBuffer->Size = NewSize;
2020-12-03 20:54:33 +03:30
SymbolBuffer->Head = NewHead;
2021-03-02 02:48:41 +03:30
}
2021-03-22 18:19:39 +04:30
WriteAddr = (PSYMBOL)((uintptr_t)SymbolBuffer->Head + (uintptr_t)Pointer * (uintptr_t)sizeof(SYMBOL));
2021-03-02 02:48:41 +03:30
WriteAddr->Type = Symbol->Type;
2021-03-22 18:19:39 +04:30
strcpy((char *)&WriteAddr->Value, (char *)&Symbol->Value);
2020-12-03 20:54:33 +03:30
}
else
{
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Write input to the appropriate address in SymbolBuffer
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
*WriteAddr = *Symbol;
2021-02-12 03:12:01 +03:30
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Update Pointer
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
SymbolBuffer->Pointer++;
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Handle Overflow
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
if (Pointer == SymbolBuffer->Size - 1)
{
//
// Allocate a new buffer for string list with doubled length
//
PSYMBOL NewHead = (PSYMBOL)malloc(2 * SymbolBuffer->Size * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
2020-12-03 20:54:33 +03:30
//
// Copy old Buffer to new buffer
//
memcpy(NewHead, SymbolBuffer->Head, SymbolBuffer->Size * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
2020-12-03 20:54:33 +03:30
//
// Free Old buffer
//
free(SymbolBuffer->Head);
//
// Upadate Head and size of SymbolBuffer
//
SymbolBuffer->Size *= 2;
SymbolBuffer->Head = NewHead;
}
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
2020-12-03 20:54:33 +03:30
return SymbolBuffer;
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
/**
*
*
*
*/
2021-03-22 18:19:39 +04:30
void
PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
PSYMBOL Symbol;
2021-02-12 03:12:01 +03:30
for (int i = 0; i < SymbolBuffer->Pointer;)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
Symbol = SymbolBuffer->Head + i;
2021-03-22 18:19:39 +04:30
2020-12-02 02:32:49 +03:30
PrintSymbol(Symbol);
2020-12-03 21:21:35 +03:30
if (Symbol->Type == SYMBOL_STRING_TYPE)
{
2021-01-14 13:36:57 +03:30
int temp = GetStringSymbolSize(Symbol);
i += temp;
2020-12-03 21:21:35 +03:30
}
else
{
i++;
}
2020-10-20 19:35:15 +03:30
}
}
2021-03-22 18:19:39 +04:30
unsigned long long int
RegisterToInt(char * str)
2020-10-20 19:35:15 +03:30
{
2020-12-02 18:11:03 +03:30
for (int i = 0; i < REGISTER_MAP_LIST_LENGTH; i++)
2020-10-22 13:53:31 +03:30
{
2020-12-02 18:11:03 +03:30
if (!strcmp(str, RegisterMapList[i].Name))
{
return RegisterMapList[i].Type;
}
2020-10-22 13:53:31 +03:30
}
2020-10-20 19:35:15 +03:30
return INVALID;
}
2021-03-22 18:19:39 +04:30
unsigned long long int
PseudoRegToInt(char * str)
2020-10-20 19:35:15 +03:30
{
2020-12-02 18:11:03 +03:30
for (int i = 0; i < PSEUDO_REGISTER_MAP_LIST_LENGTH; i++)
2020-10-22 13:53:31 +03:30
{
2020-12-02 18:11:03 +03:30
if (!strcmp(str, PseudoRegisterMapList[i].Name))
{
return PseudoRegisterMapList[i].Type;
}
2020-10-22 13:53:31 +03:30
}
2020-10-20 19:35:15 +03:30
return INVALID;
}
2021-03-22 18:19:39 +04:30
unsigned long long int
SemanticRuleToInt(char * str)
2020-10-20 19:35:15 +03:30
{
2020-12-02 18:11:03 +03:30
for (int i = 0; i < SEMANTIC_RULES_MAP_LIST_LENGTH; i++)
2020-10-28 12:29:30 +03:30
{
2020-12-02 18:11:03 +03:30
if (!strcmp(str, SemanticRulesMapList[i].Name))
{
return SemanticRulesMapList[i].Type;
}
2020-10-28 12:29:30 +03:30
}
2020-12-02 18:11:03 +03:30
return INVALID;
2020-10-20 19:35:15 +03:30
}
2021-03-22 18:19:39 +04:30
char *
HandleError(unsigned int ErrorType, char * str)
2020-12-03 18:02:49 +03:30
{
//
2021-03-22 18:19:39 +04:30
// allocate rquired memory for message
//
int MessageSize = (InputIdx - CurrentLineIdx) * 2 + 30 + 100;
char * Message = (char *)malloc(MessageSize);
//
// add line number
2020-12-03 18:02:49 +03:30
//
strcpy(Message, "Line ");
2021-03-22 18:19:39 +04:30
char * Line = (char *)malloc(16);
2020-12-03 18:02:49 +03:30
sprintf(Line, "%d:\n", CurrentLine);
strcat(Message, Line);
free(Line);
//
2021-03-22 18:19:39 +04:30
// add the line which error happened at
2020-12-03 18:02:49 +03:30
//
unsigned int LineEnd;
2021-03-22 18:19:39 +04:30
for (int i = InputIdx;; i++)
2020-12-03 18:02:49 +03:30
{
if (str[i] == '\n' || str[i] == '\0')
{
LineEnd = i;
break;
}
}
strncat(Message, (str + CurrentLineIdx), LineEnd - CurrentLineIdx);
strcat(Message, "\n");
2021-03-22 18:19:39 +04:30
//
// add pointer
2020-12-03 18:02:49 +03:30
//
char Space = ' ';
for (int i = 0; i < (CurrentTokenIdx - CurrentLineIdx); i++)
{
2021-03-22 18:19:39 +04:30
strncat(Message, &Space, 1);
}
2020-12-03 18:02:49 +03:30
strcat(Message, "^\n");
//
2021-03-22 18:19:39 +04:30
// add error cause and details
2020-12-03 18:02:49 +03:30
//
2021-03-22 18:19:39 +04:30
switch (ErrorType)
2020-12-03 18:02:49 +03:30
{
case SYNTAX_ERROR:
strcat(Message, "SyntaxError: ");
strcat(Message, "Invalid Syntax");
return Message;
case UNKOWN_TOKEN:
strcat(Message, "SyntaxError: ");
strcat(Message, "Unkown Token");
return Message;
default:
strcat(Message, "Unkown Error: ");
return Message;
}
2021-03-03 16:53:19 +03:30
}
2021-03-22 18:19:39 +04:30
int
GetIdentifierVal(TOKEN Token)
2021-03-03 16:53:19 +03:30
{
TOKEN CurrentToken;
for (uintptr_t i = 0; i < IdTable->Pointer; i++)
{
CurrentToken = *(IdTable->Head + i);
if (!strcmp(Token->Value, CurrentToken->Value))
{
return (int)i;
}
}
2021-04-11 18:27:23 +04:30
2021-03-03 16:53:19 +03:30
//
2021-04-11 18:27:23 +04:30
// if token value is not found, push the token to the token list and return corresponding id
2021-03-03 16:53:19 +03:30
//
2021-03-22 18:19:39 +04:30
CurrentToken = NewToken();
2021-03-03 16:53:19 +03:30
CurrentToken->Type = Token->Type;
strcpy(CurrentToken->Value, Token->Value);
2021-03-08 15:09:39 +03:30
IdTable = Push(IdTable, CurrentToken);
2021-03-03 16:53:19 +03:30
return IdTable->Pointer - 1;
}
2021-04-11 18:27:23 +04:30
int
LalrGetRhsSize(int RuleId)
{
int Counter = 0;
int N = LalrRhsSize[RuleId];
for (int i = 0; i < N; i++)
{
if (LalrRhs[RuleId][i].Type != EPSILON && LalrRhs[RuleId][i].Type != SEMANTIC_RULE)
{
Counter++;
}
}
return Counter;
}
BOOL
LalrIsOperandType(TOKEN Token)
{
if (Token->Type == ID)
{
return TRUE;
}
else if (Token->Type == DECIMAL)
{
return TRUE;
}
else if (Token->Type == HEX)
{
return TRUE;
}
else if (Token->Type == OCTAL)
{
return TRUE;
}
else if (Token->Type == BINARY)
{
return TRUE;
}
else if (Token->Type == REGISTER)
{
return TRUE;
}
else if (Token->Type == PSEUDO_REGISTER)
{
return TRUE;
}
else if (Token->Type == TEMP)
{
return TRUE;
}
return FALSE;
}