#c #c #parsing
#c #c #синтаксический анализ
Вопрос:
Я пытаюсь проанализировать c
файлы, используя свой пользовательский анализатор (написанный на c
). Перед началом синтаксического анализа я хотел бы избавиться от всего #define
. Я хочу, чтобы исходный файл можно было компилировать после предварительной обработки. Таким образом, лучшим способом будет запуск C Preprocessor
с файлом.
cpp myfile.cpp temp.cpp
// or
g -E myfile.cpp > templ.cpp
[Новые предложения приветствуются.]
Но из-за этого исходные строки и их номера строк будут потеряны, поскольку файл также будет содержать всю информацию заголовка, и я хочу сохранить номера строк. Итак, я решил, что выход,
- Добавьте специальный символ перед каждой строкой в исходном файле (кроме препроцессоров)
- Запустите препроцессор
- Извлеките строки с этим специальным символом и проанализируйте их
Например, типичный исходный файл будет выглядеть следующим образом:
#include<iostream>
#include"xyz.h"
int x;
#define SOME value
/*
** This is a test file
*/
typedef char* cp;
void myFunc (int* i, ABC<int, X<double> > o)
{
//...
}
class B {
};
После добавления символа это будет похоже,
#include<iostream>
#include"xyz.h"
@3@int x;
#define SOME value
@5@/*
@6@** This is a test file
@7@*/
@8@typedef char* cp;
@9@
@10@void myFunc (int* i, ABC<int, X<double> > o)
@11@{
@12@ //...
@13@}
@14@
@15@class B {
@16@};
Как только все макросы и комментарии будут удалены, у меня останутся тысячи строк, в которых несколько сотен будут оригинальным исходным кодом.
Правильный ли этот подход? Я пропустил какой-либо угловой регистр?
Комментарии:
1. Чего вы пытаетесь достичь?
2. @Michael, я хочу избавиться от макросов (т.Е.
#define
) из исходных файлов, прежде чем я начну анализировать их с помощью моего анализатора.3. Я тоже не знаю, какова ваша конечная цель. В академических целях вы, возможно, захотите взглянуть на интерфейс Clang ( clang.llvm.org ), он имеет модульную конструкцию, и это то, что вы можете интегрировать в другие приложения / инструменты.
4. @Julio, Не для академических целей. Как только разбор будет завершен, я буду модифицировать исходный код определенным образом. Однако объяснять все будет слишком сложно для написания. Я надеюсь, что, по крайней мере, мой вопрос поясняющий. Пожалуйста, дайте мне знать, если я чего-то не понимаю.
5. @iammilind: Если это не для академических целей, я думаю, что пытаться написать свой собственный интерфейс C — это своего рода безумие. Множество вещей, таких как создание экземпляра шаблона и поиск в зависимости от аргумента, может быть чрезвычайно сложным для правильной реализации, и существует по крайней мере два отличных и свободно доступных интерфейса C , которые вы можете использовать (
g
и LLVMclang
), на разработку каждого из которых уходят миллионы часов, и все еще часто содержат серьезные ошибки.
Ответ №1:
Вы понимаете, что g -E добавляет некоторые из своих собственных строк к своим выводам, которые указывают номера строк в исходном файле? Вы найдете строки, подобные
# 2 "foo.cc" 2
это указывает на то, что вы просматриваете строку 2 файла foo.cc . Эти строки вставляются всякий раз, когда нарушается обычная последовательность строк.
Комментарии:
1. Я думаю, эти строки добавлены только для заголовков. Для общего кода это не так.
2. @iammilind: нет, они добавляются после каждого изменения файла. из него можно вывести фактические номера строк.
3. @Mat, но могу ли я извлечь исходный код исходного файла? Если я предварительно обработал «x.cpp «тогда меня интересует только анализ «x.cpp «исходный код. Как правило, они загромождены множеством других
namespaces
иfunction declarations
, которые меня не интересуют.4. @iammilind: после каждой
# n "foo.cpp" x
вы знаете, что следующие строки (до следующей# q "file.x" y
) из foo.cpp строка n и следующая. итак, да, вы все время точно знаете, где находитесь.5. @Mat, ты прав. Это сэкономит мне много работы. Единственное, что я должен продолжать отслеживать для
"foo.cpp"
с помощью чиселn
иx
. В основном это отображается в начале и конце предварительно обработанного файла. Никогда не замечал этого должным образом.
Ответ №2:
imake
Программа, которая раньше поставлялась с исходными текстами X11, использовала слегка похожую систему, помечая концы строк @@
, чтобы она могла правильно их обработать после.
Выходные данные из gcc -E
обычно включают #line
директивы; возможно, вы могли бы использовать их вместо своих символов.
Комментарии:
1. Интересно. Но я не хотел бы использовать
#
, поскольку он используется и в других местах. Правильный ли текущий подход, упомянутый в вопросе?2. @iammilind: выходные данные GCC будут включать
#line
директивы, вероятно, в сокращенной форме без ключевого словаline
, как упоминал Эрнест. Вы можете использовать@99@
для обозначения начала строк. Я привел исторический прецедент использования@@
; по общему признанию, это было в конце строки, а не в начале, но@
символ — один из лучших вариантов (видимый и иначе не используемый C).