Skip to content

Parsing Pipeline

The parsing pipeline transforms a raw .cub file into validated runtime state. It runs before MiniLibX initialization, so invalid configuration or map geometry never reaches the render loop.

Runtime sequence

From `.cub` text to validated map state

This visual flow follows the real startup order: every step either prepares the next parsing stage or stops immediately through the error path.

  1. parse_file(app, path)

    Entry point that owns the full parsing sequence.

  2. has_cub_extension(path)

    Rejects input paths that do not end with `.cub`.

    bad extension -> Error
  3. read_all_text(path)

    Reads the whole file before splitting it into stable line storage.

    count_lines(text) pre-compute line count
    split_lines(text, line_count) produce char **lines
    read/allocation failure -> Error
  4. parse_headers(app, &ctx)

    Parses NO/SO/WE/EA/F/C and records the first map line as map_start.

    parse_texture(...) .xpm path, duplicate check
    parse_color(...) r,g,b in 0..255
    unknown id / duplicate / malformed value -> Error
  5. map_start < line_count

    Rejects files that provide headers but never start a map block.

    missing map block -> Error
  6. check_required_headers(app)

    Ensures all six required configuration entries were provided.

    missing section -> Error
  7. validate_map(app, lines, map_start)

    Hard gate before runtime: player, character set, and closure checks.

    validate_player exactly one N/S/E/W spawn
    validate_chars mandatory + bonus-aware alphabet
    check_enclosure BFS leak and unreachable-area checks
    invalid map -> Error
  8. parse_map(app, lines, map_start, line_count)

    Duplicates validated rows into app->map.grid.

Next stage init_player_vectors(app) → init_mlx(app) → mlx_loop

`app->map.grid` is now owned by the runtime and ready for player setup, collision, and raycasting.

The current codebase follows this order:

  1. parse_file(app, path)
  2. has_cub_extension(path)
  3. read_all_text(path)
  4. count_lines(text)
  5. split_lines(text, line_count)
  6. parse_headers(app, &ctx)
  7. reject Missing map block if no map rows follow the headers
  8. check_required_headers(app)
  9. validate_map(app, lines, map_start)
  10. parse_map(app, lines, map_start, line_count)

Each stage fails immediately when it detects invalid input or an allocation/resource issue.

parse_headers(app, &ctx) scans configuration lines until the first map-like line. It delegates value parsing to:

  • parse_texture(...) for NO, SO, WE, EA
  • parse_color(...) for F, C

This stage detects duplicate identifiers, unknown identifiers, malformed RGB values, invalid texture paths, and records map_start.

validate_map(app, lines, map_start) is the hard safety gate before graphics. It runs three checks in sequence:

  • validate_player(...): exactly one spawn among N/S/E/W
  • validate_chars(...): only supported mandatory/bonus characters
  • check_enclosure(...): BFS-based closure, leak-to-void detection, and unreachable-area rejection

If one of these checks fails, the program exits through the error path and init_mlx is never called.

After validation succeeds, parse_map(app, lines, map_start, line_count) duplicates the map rows into app->map.grid.

At that point, parsing-owned temporary line buffers can be released, while the validated map becomes part of t_app.

  • srcs/parsing/parse_file.c
  • srcs/parsing/parse_read.c
  • srcs/parsing/parse_split.c
  • srcs/parsing/parse_config.c
  • srcs/parsing/parse_textures.c
  • srcs/parsing/parse_colors.c
  • srcs/parsing/parse_map.c
  • srcs/validation/validate_map.c