why am i getting a segmentation fault

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pmake.h"


/* 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) {
    char line[MAXLINE];
    Rule *rules = NULL;
    Rule *cur_rule = NULL;
    Action *cur_action = NULL;
    Dependency *cur_dep = NULL;
    int line_num = 0;

    while (fgets(line, MAXLINE, fp) != NULL) {
        line_num++;
        if (is_comment_or_empty(line)) {
            continue;
        }

        // Remove trailing newline
        line[strlen(line) - 1] = '\0';

        // Check if line is a target
        if (line[0] == '\t') {
            // If no rule has been created yet, this is an error
            if (cur_rule == NULL) {
                fprintf(stderr, "ERROR: action line before target line at line %d", line_num);
                exit(1);

            // If no action has been created yet, create one
            } else if (cur_action == NULL) {
                cur_action = malloc(sizeof(Action));
                cur_action->args = parse_args(line);
                cur_action->next_act = NULL;
                cur_rule->actions = cur_action;

            // Otherwise, add to the end of the list of actions
            } else {
                cur_action->next_act = malloc(sizeof(Action));
                cur_action = cur_action->next_act;
                cur_action->args = parse_args(line);
                cur_action->next_act = NULL;
            }

        // Otherwise, line is a target
        } else {
            // If a rule has already been created, add it to the list of rules
            if (cur_rule != NULL) {
                cur_rule->next_rule = malloc(sizeof(Rule));
                cur_rule = cur_rule->next_rule;
            // Otherwise, create the first rule
            } else {
                cur_rule = malloc(sizeof(Rule));
                rules = cur_rule;
            }

            // Parse the target
            cur_rule->target = parse_target(line);
            cur_rule->dependencies = NULL;
            cur_rule->actions = NULL;
            cur_rule->next_rule = NULL;

            // Parse the dependencies
            char *dep_line = parse_dependencies(line);
            if (dep_line != NULL) {
                cur_dep = malloc(sizeof(Dependency));
                cur_dep->rule = find_rule(rules, dep_line);
                cur_dep->next_dep = NULL;
                cur_rule->dependencies = cur_dep;
                while ((dep_line = parse_dependencies(NULL)) != NULL) {
                    cur_dep->next_dep = malloc(sizeof(Dependency));
                    cur_dep = cur_dep->next_dep;
                    cur_dep->rule = find_rule(rules, dep_line);
                    cur_dep->next_dep = NULL;
                }

            // If there are no dependencies, set cur_dep to NULL
            } else {
                cur_dep = NULL;
            }

            // Set cur_action to NULL
            cur_action = NULL;
        }
    }
    return rules;
}
