Замена макроса во время генерации кода - PullRequest
0 голосов
/ 14 ноября 2008

В настоящее время у меня есть устаревший код, который генерирует код операции. Если в коде больше макросов, генерация кода занимает столько времени (в часах !!). Я прошел через логику, они обрабатывают макрос, ища его и делая замену каждой переменной в нем, что-то вроде вставки.
Есть ли способ, которым я могу оптимизировать его, не манипулируя строкой?

Ответы [ 3 ]

1 голос
/ 25 ноября 2008

Вы должны токенизировать свои данные перед запуском такого рода процесса. (Я не могу рекомендовать знаменитую Книгу Дракона достаточно высоко - даже древнее издание выдержало испытание временем, обновленная версия 2006 года выглядит великолепно). Компиляция - это вид работы, который лучше всего разбить на более мелкие фазы: если ваша первая фаза выполняет лексический анализ на токены, разбивая строки на ключевые слова, идентификаторы, константы и т. Д., То гораздо проще найти ссылки на макросы и посмотреть их в таблице символов. (Также сравнительно проще использовать такой инструмент, как lex или flex или один из их современных эквивалентов, чтобы выполнить эту работу за вас, чем пытаться сделать это с нуля).

Кажется, что «подсказка» равна , если в коде больше макросов, тогда генерация кода занимает так много времени . Похоже, что процесс линейный по числу макросов, что, безусловно, слишком много. Я предполагаю, что этот процесс происходит по одной строке за раз (если ваш язык позволяет это, очевидно, это имеет огромное значение, поскольку вам не нужно обрабатывать программу как одну огромную строку), а псевдокод выглядит примерно так:

for(each line in the program)
{
    for(each macro definition)
    {
        test if the macro appears;
        perform replacement if needed;
    }
}

Это явно зависит от количества макроопределений.

С токенизацией это выглядит примерно так:

for(each line in the program)
{
    tokenize the line;
    for(each token in the line)
    {
        switch(based on the token type)
        {
            case(an identifier)
                lookup the identifier in the table of macro names;
                perform replacement as necessary;
            ....
        }
    }
}

, который масштабируется в основном по размеру программы (а не по количеству определений) - поиск таблицы символов, конечно, можно выполнить с более оптимальными структурами данных, чем циклически проходить через них все, чтобы больше не становиться существенным фактором. Этот второй шаг - это то, что снова программы, такие как yacc и bison (и их более современные варианты), могут с радостью генерировать код для выполнения.

запоздалая мысль: при разборе макроса определений вы также можете сохранить их как поток токенов и отметить идентификаторы, которые являются именами-заполнителями для замены параметров. При расширении макроса переключитесь на этот поток токенов. (Опять же, что-то вроде flex легко может сделать).

0 голосов
/ 14 ноября 2008

Это действительно трудно ответить, не зная больше вашего процесса препроцессора / разбора / компиляции. Одной из идей было бы хранить имена макросов в таблице символов. При синтаксическом анализе сначала проверьте текстовые токены для этой таблицы. Если вы нашли совпадение, запишите замену в новую строку и пропустите ее через анализатор, а затем продолжите синтаксический анализ исходного текста, следуя близким скобкам макроса.

В зависимости от синтаксиса вашего кода операции, может быть другая идея - когда вы сталкиваетесь с определением макроса во время синтаксического анализа, генерируйте коды операций, но ставите заполнители вместо аргументов. Затем, когда синтаксический анализатор сталкивается с вызовами макроса, сгенерируйте код для оценки аргументов и вставьте этот код вместо заполнителей в предварительно сгенерированный код макроса.

0 голосов
/ 14 ноября 2008

У меня есть приложение, которое имеет свой собственный грамматик. Он поддерживает все типы типов данных, которые поддерживает типичный компилятор (даже макросы). Точнее, это тип компилятора, который генерирует коды операций, принимая в качестве входных данных программу (которая написана с использованием этого грамматика). Для обработки макросов используется логика замены текста Например:

Макро Добавить (a: int, b: int)

int c = a + b

Конец макроса

// Сумма программы

..

int x = 10, y = 10;

Добавить (х, у);

..

// Конец программы

После замены будет

// Сумма программы

..

int x = 10, y = 10;

int c = x + y

..

// Конец программы

Эта замена текста отнимает так много времени, то есть заменяет вызов макроса на логику макроса. Есть ли оптимальный способ сделать это?

...