Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

amanzhola/cpp-preprocessor2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

3 Commits

Repository files navigation

cpp-preprocessor2

Учебный проект: свой препроцессор C++
(раскрытие #include) с использованием:

  • std::regex
  • сырых строковых литералов (R"( ... )")
  • рекурсии
  • std::filesystem

Проект демонстрирует прохождение тестов и реальное использование препроцессора в цепочке сборки.


Идея проекта

Мы пишем собственный препроцессор, а затем используем его:

  • чтобы склеить исходники другой версии проекта в один .cpp,
  • скомпилировать этот файл,
  • и запустить тесты.

То есть препроцессор работает на практике.


Кратко о версиях

  • V0 — оркестратор (launcher):

    • компилирует V1,
    • запускает тесты V1,
    • запускает V1 в режиме --flatten,
    • компилирует результат в V2,
    • запускает тесты V2.
  • V1 — минимальная реализация препроцессора по ТЗ

    • режим --flatten (склейка проекта в один .cpp).
  • V2 — улучшенная версия:

    • убирает UTF-8 BOM,
    • нормализует CRLF,
    • нормализует пути,
    • кэширует найденные include.

Итоговая цепочка работы (что реально происходит)

V0
├─ компилирует V1
├─ запускает V1 (тесты)
├─ запускает V1 --flatten
│ └─ получает build/v2_flat.cpp
├─ компилирует build/v2_flat.cpp → v2.exe
└─ запускает v2.exe (тесты)

Главное:

  • build/v2_flat.cpp создаётся препроцессором V1.
  • Это делается рекурсией + regex, ровно теми же приёмами, которые изучались в уроке.
  • В сборочной цепочке используется режим --flatten.

Ограничение склейки include (ВАЖНО)

В режиме --flatten препроцессор раскрывает ТОЛЬКО директивы вида:

#include "..."

Директивы вида:

#include <...>

НЕ раскрываются и копируются в выходной файл без изменений.

Почему так сделано

  • системные заголовки (<iostream>, <vector> и т.д.) должны обрабатываться настоящим компилятором (g++);

  • поиск и раскрытие системных include не входит в задание;

  • это соответствует реальной практике склейки пользовательского кода:

    • unity build — компиляция проекта как одного большого файла (часто для ускорения сборки);
    • amalgamation — распространение проекта в виде одного .cpp (классический пример — SQLite).

Итог:

препроцессор склеивает пользовательский код, компилятор обрабатывает стандартную библиотеку.


Структура проекта

cpp-preprocessor2/
│
├─ README.md
├─ v0.cpp # Оркестратор: V1 → flatten → V2
│
├─ v1_parts/
│ ├─ v1_main.cpp # main() V1: тесты и режим --flatten
│ └─ v1_preprocess_impl.h
│ ├─ Preprocess # режим ТЗ
│ ├─ PreprocessOne_TZ # рекурсия для ТЗ
│ ├─ FlattenProject # режим --flatten
│ └─ PreprocessOne_Flatten # рекурсивная склейка "..."
│
├─ v2_parts/
│ ├─ v2_main.cpp # main() V2: тесты
│ └─ v2_preprocess_impl.h # улучшенная реализация
│
├─ common/
│ └─ tests_common.h # общие тесты (используются V1 и V2)
│
└─ build/
 └─ v2_flat.cpp # GENERATED: результат --flatten (создаётся V1)

Ключевые функции (кто что делает)

V1 V2

v1::Preprocess(...)
Реализация по ТЗ: раскрывает "..." и <...> по правилам задания.

v1::PreprocessOne_TZ(...)
Рекурсивная функция: читает файл построчно, заменяет #include вставкой содержимого.

v1::FlattenProject(...)
Делает "склейку" проекта в один .cpp (используется в сборке V2).

v1::PreprocessOne_Flatten(...)
Главная функция склейки:
• рекурсивно раскрывает #include "..."
НЕ раскрывает #include <...>
• игнорирует #pragma once
• формирует build/v2_flat.cpp

Улучшенная реализация препроцессора:
• удаляет BOM
• нормализует CRLF (убирает \r)
• нормализует пути
• кэширует найденные include
• проходит те же тесты


Запуск (Windows / MinGW)

Чтобы русский текст корректно отображался в консоли:

chcp 65001

Далее:

set PATH=C:\Qt\Tools\mingw1310_64\bin;%PATH%
g++ -std=gnu++17 v0.cpp -o v0.exe
v0.exe

Ожидаемый вывод (как в тренажёре)

Ключевые строки:

g++ -std=gnu++17 v1_parts/v1_main.cpp -o v1.exe
v1.exe
V1: минимальная реализация + flatten (только #include "...")
Анализируем и компилируем решение...
Запускаем тесты...
Успех!
v1.exe --flatten v2_parts/v2_main.cpp build/v2_flat.cpp v2_parts common
g++ -std=gnu++17 build/v2_flat.cpp -o v2.exe
v2.exe
V2: улучшенная версия (BOM/CRLF/normalize/кэш) + flatten
Анализируем и компилируем решение...
Запускаем тесты...
Успех!

Диаграмма вызовов функций (ASCII)

v0.exe
 ├─ system("g++ ... v1_main.cpp -> v1.exe")
 ├─ system("v1.exe") // тесты V1
 ├─ system("v1.exe --flatten ...") // склейка V2
 │ └─ v1_main.cpp: main()
 │ └─ FlattenProject(...)
 │ └─ PreprocessOne_Flatten(...)
 │ ├─ regex_match("#include \"...\"")
 │ └─ рекурсия
 ├─ system("g++ ... build/v2_flat.cpp -> v2.exe")
 └─ system("v2.exe") // тесты V2

About

Учебный проект: реализация препроцессора C++ с рекурсивным раскрытием #include, regex, filesystem и склейкой проекта в один файл.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /