В некоторых языках есть возможность передавать компилятору длинные строки, записывая их кусками в нескольких строках текстового редактора.
Для того, чтобы компилятору было ясно, что это не несколько разных строк, а одна длинная, перед переводами строки ставят знак "обратный слеш" - \
Как это обрабатывать. Во первых, есть разница - встречается обратный слеш в символьной строке или в основном тексте (например у budden специальные строки, из которых удаляются начальные пробелы). Эта разница заключается в том, что содержимое строки и код описывают разные правила грамматики. Значит описание слеша попадёт в граматику минимум два раза. Во-вторых, есть ещё комментарии, которые тоже могут обрабатываться особо.
Почему надо вносить обработку склеиваний в грамматику комиплятора, а не сделать препроцессор, который всё просклеивает заранее и передаст обработанный текст на вход компилятора? Потому что в первом случае информация об исходных номерах строк доступна, а во-втором потеряется.
Почему потеряется? Потому что директива #line должна располагаться на отдельной строке. Это значит, что нельзя указать разные номера исходных строк для разных частей длинной "логической" строки.
Как задача передачи информации об исходных положениях токенов решается в компиляторе C++? Неизвестно.
preprocessor macro __LINE__ and __FILE__. They are predefined macros and part of the C/C++ standard. During preprocessing, they are replaced respectively by a constant string holding an integer representing the current line number and by the current file name.
The #line directive tells the preprocessor ( почему не tells to the compiler??? ) to change the compiler's internally stored line number and filename to a given line number and filename.
The C preprocessor informs the C compiler of the location in your source code where each token came from.
#line digit-sequence ["filename"]
#line preprocessing_expression
http://www.complete-concrete-concise.co … -directive
# must be the first character on the line or the first character on the line following optional white space.
Spaces or tabs are permitted between the # and line, but not escape characters or other symbols or macros.
The preprocessor removes white space and concatenates the # and line together.
If anything follows the #line directive (other than white space) then the program is malformed.
https://gcc.gnu.org/onlinedocs/cpp/Line-Control.html
#line do not have any effect on ‘#include’’s idea of the directory containing the current file.
Если бы от препроцессора компилятору передавался бы не отпрепроцешшеный текст, а набор фрагментов текста с позициями и именами исходных файлов, то можно было бы обработку склеивания разместить в препроцессоре.
Для того, чтобы передавать набор фрагментов текста и позиции нужно определить API (и ABI ?).
Похожее API есть у сканнера (он же лексер), там дополнительно передаётся "код токена".
Собственно, надо придумать, как к парсеру прикрутить похожий интерфейс, чтобы состыковать выход парсера предыдущей стадии разбора с входом сканера следующей стадии. В случае использования scannerless-парсеров задача их последовательной состыковки всё равно остаётся.
Схожая задача разбиения грамматики на уровни возникает так же при раскрашивании текста (синтаксической подсветке). Есть грамматика для раскрашивания (попроще), а есть для анализа (посложнее). Хорошо бы, чтобы вторая пользовалась полуфабрикатами, произведёнными первой.
Отредактировано Лис (2018-01-03 12:34:08)