parse_file should create rule_node and/or action_node from the given file fp. fp will have the following format:
main : linked_list.o main.o
	gcc -Wall -g -std=gnu99 -o main linked_list.o main.o

main.o : main.c linked_list.h 
	gcc -Wall -g -std=gnu99 -c main.c

linked_list.o : linked_list.c linked_list.h
	gcc -Wall -g -std=gnu99 -c linked_list.c
#define MAXLINE 256

typedef struct action_node {
    char **args;  // An array of strings suitable to be passed to execvp
    struct action_node *next_act;
} Action;

typedef struct dep_node {
    struct rule_node *rule;
    struct dep_node *next_dep;
} Dependency;

typedef struct rule_node {
    char *target;
    Dependency *dependencies;
    Action *actions;
    struct rule_node *next_rule;
} Rule;

int is_comment_or_empty(const char *line) {
    for (int i = 0; i < strlen(line); i++){
        if (line[i] == '#') {
            return 1;
        }
        if (line[i] != '\t' && line[i] != ' ') {
            return 0;
        }
    }
    return 1;
}

/* Read from the open file fp, and create the linked data structure
   that represents the Makefile contained in the file.
   See the top of pmake.h for the specification of Makefile contents.
 */
Rule *parse_file(FILE *fp) {
    // Implement this function and remove the stubbed return statement below.
    
    // Create the rules linked_list
    Rule rules = malloc(sizeof(Rule));
    Rule *cur_rule = &rules;


    // Read each line in the file
    char line[MAXLINE + 1];
    while (fgets(line, MAXLINE + 1, fp) != NULL) {
        if (is_comment_or_empty(line) == 1) {
            continue;
        }

        if( myString[0] == ' ' || myString[0] == '\t' ){
            // Create action_node

            // Insert node to the end of rules
        } else {
            // create rule_node

            // Insert node to the end of rules
        }

    }
}