#include "parser.h" #include "lexer.h" #include "types.h" #include #include #include GroundProgram createGroundProgram() { GroundProgram gp; gp.size = 0; gp.instructions = NULL; return gp; } void addInstructionToProgram(GroundProgram* gp, GroundInstruction instruction) { gp->size++; GroundInstruction* ptr = realloc(gp->instructions, gp->size * sizeof(GroundInstruction)); if (ptr == NULL) { perror("Couldn't allocate memory for instruction"); exit(EXIT_FAILURE); } gp->instructions = ptr; gp->instructions[gp->size - 1] = instruction; } void freeGroundProgram(GroundProgram* gp) { for (size_t i = 0; i < gp->size; i++) { freeGroundInstruction(&gp->instructions[i]); } free(gp->instructions); gp->instructions = NULL; gp->size = 0; } // Helper: Check if a string is an integer static bool isInteger(const char* str) { if (str == NULL || *str == '\0') return false; size_t i = 0; if (str[0] == '-' || str[0] == '+') i++; if (str[i] == '\0') return false; for (; str[i] != '\0'; i++) { if (!isdigit(str[i])) return false; } return true; } // Helper: Check if a string is a double static bool isDouble(const char* str) { if (str == NULL || *str == '\0') return false; bool hasDecimal = false; size_t i = 0; if (str[0] == '-' || str[0] == '+') i++; if (str[i] == '\0') return false; for (; str[i] != '\0'; i++) { if (str[i] == '.') { if (hasDecimal) return false; hasDecimal = true; } else if (!isdigit(str[i])) { return false; } } return hasDecimal; } // Helper: Parse an argument token into a GroundArg static GroundArg parseArgument(const char* token) { if (token[0] == '"') { // String literal - remove quotes size_t len = strlen(token); char* strVal = strndup(token + 1, len - 2); GroundValue val = createStringGroundValue(strVal); free(strVal); return createValueGroundArg(val); } else if (token[0] == '\'') { // Char literal char charVal = token[1]; return createValueGroundArg(createCharGroundValue(charVal)); } else if (strcmp(token, "true") == 0) { return createValueGroundArg(createBoolGroundValue(true)); } else if (strcmp(token, "false") == 0) { return createValueGroundArg(createBoolGroundValue(false)); } else if (token[0] == '$') { // Value reference return createRefGroundArg(VALREF, token + 1); } else if (token[0] == '&') { // Direct reference return createRefGroundArg(DIRREF, token + 1); } else if (token[0] == '%') { // Line reference or label return createRefGroundArg(LINEREF, token + 1); } else if (token[0] == '!') { // Function reference return createRefGroundArg(FNREF, token + 1); } else if (token[0] == '-') { // Could be type reference or negative number if (strlen(token) > 1 && !isdigit(token[1])) { // Type reference (e.g., -int, -string) return createRefGroundArg(LABEL, token + 1); // Using LABEL for type refs } // Fall through to number parsing } // Try to parse as number if (isInteger(token)) { int64_t intVal = atoll(token); return createValueGroundArg(createIntGroundValue(intVal)); } else if (isDouble(token)) { double dblVal = atof(token); return createValueGroundArg(createDoubleGroundValue(dblVal)); } // Unknown token type fprintf(stderr, "Warning: Unknown argument type for token: %s\n", token); return createRefGroundArg(VALREF, token); } // Helper: Convert instruction string to GroundInstType static GroundInstType getInstructionType(const char* inst) { if (strcmp(inst, "if") == 0) return IF; if (strcmp(inst, "jump") == 0) return JUMP; if (strcmp(inst, "end") == 0) return END; if (strcmp(inst, "input") == 0 || strcmp(inst, "stdin") == 0) return INPUT; if (strcmp(inst, "print") == 0 || strcmp(inst, "stdout") == 0) return PRINT; if (strcmp(inst, "println") == 0 || strcmp(inst, "stdlnout") == 0) return PRINTLN; if (strcmp(inst, "set") == 0) return SET; if (strcmp(inst, "gettype") == 0) return GETTYPE; if (strcmp(inst, "exists") == 0) return EXISTS; if (strcmp(inst, "setlist") == 0) return SETLIST; if (strcmp(inst, "setlistat") == 0) return SETLISTAT; if (strcmp(inst, "getlistat") == 0) return GETLISTAT; if (strcmp(inst, "getlistsize") == 0) return GETLISTSIZE; if (strcmp(inst, "listappend") == 0) return LISTAPPEND; if (strcmp(inst, "getstrsize") == 0) return GETSTRSIZE; if (strcmp(inst, "getstrcharat") == 0) return GETSTRCHARAT; if (strcmp(inst, "add") == 0) return ADD; if (strcmp(inst, "subtract") == 0) return SUBTRACT; if (strcmp(inst, "multiply") == 0) return MULTIPLY; if (strcmp(inst, "divide") == 0) return DIVIDE; if (strcmp(inst, "equal") == 0) return EQUAL; if (strcmp(inst, "inequal") == 0) return INEQUAL; if (strcmp(inst, "not") == 0) return NOT; if (strcmp(inst, "greater") == 0) return GREATER; if (strcmp(inst, "lesser") == 0) return LESSER; if (strcmp(inst, "stoi") == 0) return STOI; if (strcmp(inst, "stod") == 0) return STOD; if (strcmp(inst, "tostring") == 0) return TOSTRING; if (strcmp(inst, "fun") == 0) return FUN; if (strcmp(inst, "return") == 0) return RETURN; if (strcmp(inst, "endfun") == 0) return ENDFUN; if (strcmp(inst, "pusharg") == 0) return PUSHARG; if (strcmp(inst, "call") == 0) return CALL; if (strcmp(inst, "struct") == 0) return STRUCT; if (strcmp(inst, "endstruct") == 0) return ENDSTRUCT; if (strcmp(inst, "init") == 0) return INIT; if (strcmp(inst, "use") == 0) return USE; if (strcmp(inst, "extern") == 0) return EXTERN; fprintf(stderr, "Error: Unknown instruction: %s\n", inst); exit(EXIT_FAILURE); } GroundProgram parseFile(const char* file) { GroundProgram program = createGroundProgram(); // First, lex the file LexedFile lexed = lexFile(file); // Parse each line for (size_t lineNum = 0; lineNum < lexed.lineCount; lineNum++) { TokenLine line = lexed.lines[lineNum]; // Skip empty lines if (line.count == 0) { continue; } // Check if first token is a label size_t tokenStart = 0; if (line.tokens[0].text[0] == '@') { // TODO: Handle labels - you might want to store them separately // For now, skip to next token tokenStart = 1; if (tokenStart >= line.count) continue; } // First non-label token is the instruction const char* instToken = line.tokens[tokenStart].text; GroundInstType instType = getInstructionType(instToken); GroundInstruction inst = createGroundInstruction(instType); // Parse remaining tokens as arguments for (size_t i = tokenStart + 1; i < line.count; i++) { GroundArg arg = parseArgument(line.tokens[i].text); addArgToInstruction(&inst, arg); } addInstructionToProgram(&program, inst); } // Clean up lexed data freeLexedFile(&lexed); return program; }