sps.c
State parseCommands(Program *prog, char *cmdStr) {
    // command delimiters
    char *delims = ";";
    // all commands except selection because of their weird syntax
    const Command knownCommands[] = {
        // Custom commands (not in official specification)
        {.name="print", .fn=print_cmd},
        {.name="dump", .fn=dump_cmd},
        // Selection
        {.name="[min]", .fn=selectMin_cmd},
        {.name="[max]", .fn=selectMax_cmd},
        {.name="[find ", .fn=selectFind_cmd},
        {.name="[_]", .fn=selectLoad_cmd},
        // Layout commands
        {.name="irow", .fn=irow_cmd},
        {.name="arow", .fn=arow_cmd},
        {.name="drow", .fn=drow_cmd},
        {.name="icol", .fn=icol_cmd},
        {.name="acol", .fn=acol_cmd},
        {.name="dcol", .fn=dcol_cmd},
        // Data commands
        {.name="set ", .fn=set_cmd},
        {.name="clear", .fn=clear_cmd},
        {.name="swap ", .fn=swap_cmd},
        {.name="sum ", .fn=sum_cmd},
        {.name="avg ", .fn=avg_cmd},
        {.name="count ", .fn=count_cmd},
        {.name="len ", .fn=len_cmd},
        // Variable commands
        {.name="def _", .fn=def_cmd},
        {.name="use _", .fn=use_cmd},
        {.name="inc _", .fn=inc_cmd},
        {.name="[set]", .fn=selectStore_cmd},
        // Control commands
        {.name="goto ", .fn=goto_cmd},
        {.name="iszero _", .fn=iszero_cmd},
        {.name="sub _", .fn=sub_cmd},
    };
    const int NUM_KNOWN_CMDS = sizeof(knownCommands) / sizeof(Command);
    // the imaginary reading head of cmdStr
    int strIndex=0;

    while (true) {
        bool found = false;
        // check for command
        for (int j=0; j < NUM_KNOWN_CMDS; j++) {
            // if the command is found at the beginning of current index
            if (strbgn(&cmdStr[strIndex], knownCommands[j].name) == 0) {
                strIndex += strlen(knownCommands[j].name);
                addCommand(prog, &knownCommands[j]);
                found = true;
                break;
            }
        }
        // check for the weird coordinate selection command
        if (!found && (cmdStr[strIndex] == '[')) {
            const Command select = {.fn=selectCoords_cmd};
            addCommand(prog, &select);
            found = true;
            // strIndex doesn't shift
            // because the command is its own argument if it makes any sense
        }

        if (!found)
            return ERR_COMMAND_NOT_FOUND;
        // buffer for command's arguments
        char argBuf[MAX_COMMAND_LENGTH];
        // this might cause some issues later, now commands can be in
        // quotation marks and escaping is allowed
        size_t shift = parseString(argBuf, &cmdStr[strIndex], delims);
        // to make the next line cleaner
        Command *lastCmdPtr = &prog->cmds[prog->len - 1];
        lastCmdPtr->argStr = malloc((strlen(argBuf) + 1) * sizeof(char));
        if (lastCmdPtr->argStr == NULL)
            return ERR_MEMORY;
        strcpy(lastCmdPtr->argStr, argBuf);

        // +1 to skip the delimiter
        strIndex += shift + 1;
        // if there is delimiter, there maust be another command
        if (cmdStr[strIndex-1] == ';')
            continue;
        // if there is nothing left
        if (cmdStr[strIndex-1] == '\0')
            break;
    }
    return SUCCESS;
}
// takes commands as a string
// and writes them into the program structure
takes commands as a string
and writes them into the program structure
takes commands as a string and writes them into the program structure
State parseCommands(Program *prog, char *cmdStr) {
    char *delims = ";";
    const Command knownCommands[] = {
        {.name="print", .fn=print_cmd},
        {.name="dump", .fn=dump_cmd},
        {.name="[min]", .fn=selectMin_cmd},
        {.name="[max]", .fn=selectMax_cmd},
        {.name="[find ", .fn=selectFind_cmd},
        {.name="[_]", .fn=selectLoad_cmd},
        {.name="irow", .fn=irow_cmd},
        {.name="arow", .fn=arow_cmd},
        {.name="drow", .fn=drow_cmd},
        {.name="icol", .fn=icol_cmd},
        {.name="acol", .fn=acol_cmd},
        {.name="dcol", .fn=dcol_cmd},
        {.name="set ", .fn=set_cmd},
        {.name="clear", .fn=clear_cmd},
        {.name="swap ", .fn=swap_cmd},
        {.name="sum ", .fn=sum_cmd},
        {.name="avg ", .fn=avg_cmd},
        {.name="count ", .fn=count_cmd},
        {.name="len ", .fn=len_cmd},
        {.name="def _", .fn=def_cmd},
        {.name="use _", .fn=use_cmd},
        {.name="inc _", .fn=inc_cmd},
        {.name="[set]", .fn=selectStore_cmd},
        {.name="goto ", .fn=goto_cmd},
        {.name="iszero _", .fn=iszero_cmd},
        {.name="sub _", .fn=sub_cmd},
    };
    const int NUM_KNOWN_CMDS = sizeof(knownCommands) / sizeof(Command);
    int strIndex=0;
    while (true) {
        bool found = false;
        for (int j=0; j < NUM_KNOWN_CMDS; j++) {
            if (strbgn(&cmdStr[strIndex], knownCommands[j].name) == 0) {
                strIndex += strlen(knownCommands[j].name);
                addCommand(prog, &knownCommands[j]);
                found = true;
                break;
            }
        }
        if (!found && (cmdStr[strIndex] == '[')) {
            const Command select = {.fn=selectCoords_cmd};
            addCommand(prog, &select);
            found = true;
        }
        if (!found)
            return ERR_COMMAND_NOT_FOUND;
        char argBuf[MAX_COMMAND_LENGTH];
        size_t shift = parseString(argBuf, &cmdStr[strIndex], delims);
        Command *lastCmdPtr = &prog->cmds[prog->len - 1];
        lastCmdPtr->argStr = malloc((strlen(argBuf) + 1) * sizeof(char));
        if (lastCmdPtr->argStr == NULL)
            return ERR_MEMORY;
        strcpy(lastCmdPtr->argStr, argBuf);
        strIndex += shift + 1;
        if (cmdStr[strIndex-1] == ';')
            continue;
        if (cmdStr[strIndex-1] == '\0')
            break;
    }
    return SUCCESS;
}
State parseCommands ( Program * prog , char * cmdStr ) { char * delims = " " ; const Command knownCommands [ ] = { { . name = " " , . fn = print_cmd } , { . name = " " , . fn = dump_cmd } , { . name = " " , . fn = selectMin_cmd } , { . name = " " , . fn = selectMax_cmd } , { . name = " " , . fn = selectFind_cmd } , { . name = " " , . fn = selectLoad_cmd } , { . name = " " , . fn = irow_cmd } , { . name = " " , . fn = arow_cmd } , { . name = " " , . fn = drow_cmd } , { . name = " " , . fn = icol_cmd } , { . name = " " , . fn = acol_cmd } , { . name = " " , . fn = dcol_cmd } , { . name = " " , . fn = set_cmd } , { . name = " " , . fn = clear_cmd } , { . name = " " , . fn = swap_cmd } , { . name = " " , . fn = sum_cmd } , { . name = " " , . fn = avg_cmd } , { . name = " " , . fn = count_cmd } , { . name = " " , . fn = len_cmd } , { . name = " " , . fn = def_cmd } , { . name = " " , . fn = use_cmd } , { . name = " " , . fn = inc_cmd } , { . name = " " , . fn = selectStore_cmd } , { . name = " " , . fn = goto_cmd } , { . name = " " , . fn = iszero_cmd } , { . name = " " , . fn = sub_cmd } , } ; const int NUM_KNOWN_CMDS = sizeof ( knownCommands ) / sizeof ( Command ) ; int strIndex = 0 ; while ( true ) { bool found = false ; for ( int j = 0 ; j < NUM_KNOWN_CMDS ; j ++ ) { if ( strbgn ( & cmdStr [ strIndex ] , knownCommands [ j ] . name ) == 0 ) { strIndex += strlen ( knownCommands [ j ] . name ) ; addCommand ( prog , & knownCommands [ j ] ) ; found = true ; break ; } } if ( ! found && ( cmdStr [ strIndex ] == ' ' ) ) { const Command select = { . fn = selectCoords_cmd } ; addCommand ( prog , & select ) ; found = true ; } if ( ! found ) return ERR_COMMAND_NOT_FOUND ; char argBuf [ MAX_COMMAND_LENGTH ] ; size_t shift = parseString ( argBuf , & cmdStr [ strIndex ] , delims ) ; Command * lastCmdPtr = & prog -> cmds [ prog -> len - 1 ] ; lastCmdPtr -> argStr = malloc ( ( strlen ( argBuf ) + 1 ) * sizeof ( char ) ) ; if ( lastCmdPtr -> argStr == NULL ) return ERR_MEMORY ; strcpy ( lastCmdPtr -> argStr , argBuf ) ; strIndex += shift + 1 ; if ( cmdStr [ strIndex - 1 ] == ' ' ) continue ; if ( cmdStr [ strIndex - 1 ] == ' \0 ' ) break ; } return SUCCESS ; }
takes commands as a string
and writes them into the program structure
takes commands as a string and writes them into the program structure
// command delimiters // all commands except selection because of their weird syntax // Custom commands (not in official specification) // Selection // Layout commands // Data commands // Variable commands // Control commands // the imaginary reading head of cmdStr // check for command // if the command is found at the beginning of current index // check for the weird coordinate selection command // strIndex doesn't shift // because the command is its own argument if it makes any sense // buffer for command's arguments // this might cause some issues later, now commands can be in // quotation marks and escaping is allowed // to make the next line cleaner // +1 to skip the delimiter // if there is delimiter, there maust be another command // if there is nothing left