1
0
Fork 0
mirror of https://github.com/suchmememanyskill/TegraExplorer.git synced 2025-02-21 07:55:36 +00:00
TegraExplorer/source/tegraexplorer/script/parser.c

263 lines
9.3 KiB
C
Raw Normal View History

2020-11-06 21:19:29 +01:00
#include "args.h"
2020-03-31 14:24:34 +02:00
#include "parser.h"
2020-11-06 21:19:29 +01:00
#include "types.h"
#include "list.h"
2020-03-31 14:24:34 +02:00
#include "functions.h"
2020-11-06 21:19:29 +01:00
#include "scriptCtx.h"
#include "lexer.h"
#include <string.h>
#include "../../mem/heap.h"
2020-04-03 19:07:42 +02:00
#include "../utils/utils.h"
2020-11-06 21:19:29 +01:00
#include "../../storage/nx_sd.h"
#include "../../gfx/gfx.h"
#include "../../hid/hid.h"
2020-11-06 21:19:29 +01:00
#include "../gfx/gfxutils.h"
2020-03-30 20:15:07 +02:00
2020-11-06 21:19:29 +01:00
//#define DPRINTF(str, ...) printf(str, __VA_ARGS__)
#define DPRINTF
2020-03-30 20:15:07 +02:00
2020-11-06 21:19:29 +01:00
#define findNextCharsCtx(ctx, targets) findNextChars(&(ctx->curPos), targets)
2020-03-30 20:15:07 +02:00
2020-11-06 21:19:29 +01:00
int checkIfVar(u16 token) {
return (token == StrLit || token == IntLit || token == Variable || token == RSBracket);
2020-03-30 20:15:07 +02:00
}
2020-11-06 21:19:29 +01:00
void printToken(lexarToken_t* token) {
switch (token->token) {
case 1:
gfx_printf("%s ", token->text);
break;
case 6:
//printf("%d: '%s'\n", vec.tokens[i].token, vec.tokens[i].text);
gfx_printf("\"%s\" ", token->text);
break;
case 7:
//printf("%d: %d\n", vec.tokens[i].token, vec.tokens[i].val);
gfx_printf("%d ", token->val);
break;
default:
//printf("%d: %c\n", vec.tokens[i].token, lexarDebugGetTokenC(vec.tokens[i].token));
gfx_printf("%c ", lexarDebugGetTokenC(token->token));
break;
2020-03-31 00:09:23 +02:00
}
}
2020-11-06 21:19:29 +01:00
scriptResult_t runFunction(scriptCtx_t* ctx) {
dictValue_t res = solveEquation(ctx, &ctx->script->tokens[ctx->startEq], ctx->curPos - ctx->startEq);
if (res.varType == ErrType)
return scriptResultCreate(res.integer, &ctx->script->tokens[ctx->startEq]);
ctx->startEq = ctx->curPos;
if (ctx->varToken.token != Invalid) { // we should not assign null's
ctx->varToken.token = Invalid;
if (ctx->varIndexSet) {
ctx->varIndexSet = 0;
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (!(arrayVal == NULL || arrayVal->arrayLen <= ctx->varIndex)) {
if (arrayVal->varType == IntArrayType && res.varType == IntType) {
arrayVal->integerArray[ctx->varIndex] = res.integer;
}
else if (arrayVal->varType == StringArrayType && res.varType == StringType) {
free(arrayVal->stringArray[ctx->varIndex]);
arrayVal->stringArray[ctx->varIndex] = res.string;
}
else if (arrayVal->varType == ByteArrayType && res.varType == IntType) {
arrayVal->byteArray[ctx->varIndex] = (u8)(res.integer & 0xFF);
}
else {
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->startEq]);
}
}
else {
return scriptResultCreate(ERRNOVAR, &ctx->script->tokens[ctx->startEq]);
}
}
else {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), res));
}
2020-04-01 00:17:45 +02:00
}
else {
2020-11-06 21:19:29 +01:00
freeDictValueOnVar(res);
2020-04-01 00:17:45 +02:00
}
2020-03-30 20:15:07 +02:00
2020-11-06 21:19:29 +01:00
return scriptResultCreate(0, 0);
2020-03-30 20:15:07 +02:00
}
2020-11-06 21:19:29 +01:00
// TODO
// Make sure mem gets free'd properly
// Fix bug that custom functions cannot be run from end of script
// add arrays
2020-11-06 21:19:29 +01:00
#define RUNFUNCWITHPANIC(ctx) scriptResult_t res = runFunction(ctx); if (res.resCode != 0) return res
2020-11-06 21:19:29 +01:00
scriptResult_t mainLoop(scriptCtx_t* ctx) {
for (ctx->curPos = 0; ctx->curPos < ctx->script->stored; ctx->curPos++) {
u32 i = ctx->curPos;
lexarToken_t curToken = ctx->script->tokens[i];
//printToken(&curToken);
2020-11-06 21:19:29 +01:00
if (checkIfVar(ctx->lastToken.token) && curToken.token == Variable) {
RUNFUNCWITHPANIC(ctx);
}
else if (curToken.token == Equal) {
// Set last var to lastToken, if lastToken is var
if (ctx->lastToken.token == RSBracket) {
int layer = 0;
i = ctx->lastTokenPos - 1;
for (; i > 0; i--) {
if (ctx->script->tokens[i].token == RSBracket)
layer++;
else if (ctx->script->tokens[i].token == LSBracket) {
if (layer == 0)
break;
layer--;
}
}
i--;
if (ctx->script->tokens[i].token == Variable) {
dictValue_t index = solveEquation(ctx, &ctx->script->tokens[i + 2], ctx->lastTokenPos - i - 2);
ctx->lastTokenPos = i;
ctx->lastToken = ctx->script->tokens[i];
if (index.varType == IntType) {
ctx->varIndex = index.integer;
ctx->varIndexSet = 1;
if (ctx->varIndexSet) {
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (arrayVal == NULL) {
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->varIndex < 0 || ctx->varIndex >= arrayVal->arrayLen || arrayVal->varType < IntArrayType)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
}
else
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->curPos]);
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
2020-11-06 21:19:29 +01:00
if (ctx->lastToken.token == Variable) {
ctx->startEq = ctx->curPos + 1;
ctx->varToken = ctx->lastToken;
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
2020-11-06 21:19:29 +01:00
//printf("Setting token %s to next assignment", ctx->lastToken.text);
2020-11-06 21:19:29 +01:00
// !! check prev for ] for arrays
}
else if (curToken.token == LBracket) {
i++;
int distance = distanceBetweenTokens(&ctx->script->tokens[i], ctx->script->stored - i, LBracket, RBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
2020-11-06 21:19:29 +01:00
i += distance;
ctx->curPos = i;
2020-11-06 21:19:29 +01:00
if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
continue;
}
else if (curToken.token == LCBracket) {
if (ctx->lastToken.token == Equal && ctx->varToken.token == Variable) {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), DictValueCreate(JumpType, 0, ctx->curPos)));
ctx->varToken.token = Invalid;
setCurIndentInstruction(ctx, 1, -1);
}
2020-11-06 21:19:29 +01:00
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
}
2020-03-31 14:24:34 +02:00
2020-11-06 21:19:29 +01:00
ctx->startEq = ctx->curPos + 1;
2020-11-06 21:19:29 +01:00
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active) {
if (ins.skip) {
int distance = distanceBetweenTokens(&ctx->script->tokens[i + 1], ctx->script->stored - i - 1, LCBracket, RCBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
ctx->curPos += distance + 1;
ctx->startEq = ctx->curPos + 1;
}
else {
ctx->indentLevel++;
}
}
else
return scriptResultCreate(ERRINACTIVEINDENT, &ctx->script->tokens[ctx->curPos]);
}
2020-11-06 21:19:29 +01:00
else if (curToken.token == RCBracket) {
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
if (i != ctx->curPos)
continue;
}
2020-11-06 21:19:29 +01:00
ctx->indentLevel--;
2020-11-06 21:19:29 +01:00
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active && ins.jump) {
ctx->curPos = ins.jumpLoc - 1;
}
2020-03-31 22:01:20 +02:00
2020-11-06 21:19:29 +01:00
ctx->startEq = ctx->curPos + 1;
}
else if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
2020-03-31 22:01:20 +02:00
2020-11-06 21:19:29 +01:00
ctx->lastToken = ctx->script->tokens[ctx->curPos];
ctx->lastTokenPos = ctx->curPos;
2020-03-31 22:01:20 +02:00
}
2020-11-06 21:19:29 +01:00
return scriptResultCreate(0, 0);
}
2020-11-06 21:19:29 +01:00
const char* functionFails[] = {
"An invalid operation was performed",
"Double Nots are not allowed",
"A syntax error was found",
"The recieved type was incorrect",
"The variable could not be found",
"The specified function could not be found",
"An inactive indent was found"
};
2020-03-31 14:24:34 +02:00
2020-11-06 21:19:29 +01:00
void startScript(char* path) {
char* file = sd_file_read(path, NULL);
2020-03-31 14:24:34 +02:00
2020-11-06 21:19:29 +01:00
if (file == NULL)
return;
2020-03-31 14:24:34 +02:00
2020-03-30 20:15:07 +02:00
gfx_clearscreen();
2020-04-01 00:17:45 +02:00
2020-11-06 21:19:29 +01:00
scriptCtx_t ctx = createScriptCtx();
lexarVector_t vec = lexarGo(file);
free(file);
ctx.script = &vec;
2020-03-30 20:15:07 +02:00
2020-11-06 21:19:29 +01:00
scriptResult_t res = mainLoop(&ctx);
gfx_printf("end of script\n");
2020-03-30 20:15:07 +02:00
2020-11-06 21:19:29 +01:00
if (res.resCode) {
gfx_printf("[ERROR] %d\n%s\nNear:", res.resCode, functionFails[res.resCode - 1]);
printToken(res.nearToken);
}
2020-11-06 21:19:29 +01:00
gfx_printf("\n\n");
//mainLoop2(&ctx, &vec);
lexarVectorClear(&vec);
destroyScriptCtx(&ctx);
hidWait();
2020-03-30 20:15:07 +02:00
}