C: Преобразовать A? B: C, в если (A) B еще C

Я искал инструмент, который может преобразовать выражения кода C для формы:

a = (A) ? B : C;

в синтаксис 'по умолчанию' с if/else операторы:

if (A)
  a = B
else
  a = C

Кто-то знает инструмент, это способно, чтобы сделать такое преобразование?

Я работаю с GCC 4.4.2 и создаю предварительно обработанный файл с -E но не хочу такие структуры в нем.

Править: Следующий код должен быть преобразован, также:

a = ((A) ? B : C)->b;
5
задан tur1ng 11 March 2010 в 18:53
поделиться

5 ответов

Coccinelle может сделать это довольно легко.

Coccinelle - это механизм сопоставления программ и преобразования, который предоставляет язык SmPL (Semantic Patch Language) для указания желаемых совпадений и преобразований в коде C . Первоначально Coccinelle была нацелена на выполнение побочных изменений в Linux. Такие изменения включают изменения, которые необходимы в клиентском коде в ответ на изменения в библиотечных API, и могут включать такие изменения, как переименование {{1} } функцию, добавив аргумент функции , значение которого так или иначе зависит от контекста, и реорганизуя структуру данных . Помимо побочных эволюций, Coccinelle успешно используется (нами и другими) для поиска и исправления ошибок в системном коде.

РЕДАКТИРОВАТЬ: Пример семантического патча:

@@ expression E; constant C; @@
(
  !E & !C
|
- !E & C
+ !(E & C)
)

Из документации:

Шаблон! X & y.Выражение этой формы почти всегда бессмысленно, потому что оно объединяет логический оператор с битовым оператором. В частности, если крайний правый бит y равен 0, результатом всегда будет 0. Этот семантический патч фокусируется на случае, когда y является константой.

У вас есть хороший набор примеров здесь .

Список рассылки действительно активен и полезен.

12
ответ дан 18 December 2019 в 09:49
поделиться

Если такие операторы очень регулярны, почему бы не запустить ваши файлы через небольшой Perl-скрипт? Основная логика поиска и преобразования проста для вашей строки примера. Вот простой подход:

use strict;
while(<>) {
    my $line = $_;
    chomp($line);
    if ( $line =~ m/(\S+)\s*=\s*\((\s*\S+\s*)\)\s*\?\s*(\S+)\s*:\s*(\S+)\s*;/ ) {
        print "if(" . $2 . ")\n\t" . $1 . " = " . $3 . "\nelse\n\t" . $1 . " = " . $4 . "\n";
    } else {
        print $line . "\n";
    }
}
exit(0);

Вы бы запустили его так:

perl transformer.pl < foo.c > foo.c.new

Конечно, становится все труднее и труднее, если текстовый шаблон не такой регулярный, как тот, который вы опубликовали. Но бесплатно, быстро и легко попробовать.

0
ответ дан 18 December 2019 в 09:49
поделиться

Следующий семантический патч для Coccinelle выполнит преобразование.

@@
expression E1, E2, E3, E4;
@@

- E1 = E2 ? E3 : E4;
+ if (E2)
+   E1 = E3;
+ else
+   E1 = E4;

@@
type T;
identifier E5;
T *E3;
T *E4;
expression E1, E2;
@@

- E1 = ((E2) ? (E3) : (E4))->E5;
+ if (E2)
+   E1 = E3->E5;
+ else
+   E1 = E4->E5;


@@
type T;
identifier E5;
T E3;
T E4;
expression E1, E2;
@@

- E1 = ((E2) ? (E3) : (E4)).E5;
+ if (E2)
+   E1 = (E3).E5;
+ else
+   E1 = (E4).E5;
4
ответ дан 18 December 2019 в 09:49
поделиться

Я не знаю о такой вещи, как тернарный оператор встроен в спецификации языка как сокращение для логики if... единственный способ, который я могу придумать, это вручную искать эти строки и переписывать их в форму, где используется if. ... как общее мнение, троичный оператор работает следующим образом

expr_is_true ? exec_if_expr_is_TRUE : exec_if_expr_is_FALSE;

Если выражение оценивается как истинное, выполняется часть между ? и :, иначе выполняется последняя часть между : и ;. Если выражение оценивается как false

expr_is_false ? exec_if_expr_is_FALSE : exec_if_expr_is_TRUE;
0
ответ дан 18 December 2019 в 09:49
поделиться

Инструментарий DMS Software Reengineering Toolkit может сделать это, применяя преобразования программы.

Конкретное преобразование DMS для вашего конкретного примера:

domain C.

rule ifthenelseize_conditional_expression(a:lvalue,A:condition,B:term,C:term):
stmt -> stmt
=  " \a = \A ? \B : \C; "
-> " if (\A) \a = \B;  else \a=\C ; ".

Для другого случая вам понадобится другое правило, но его так же легко выразить.

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

Есть некоторые проблемы с директивами препроцессирования, если вы намерены их сохранить. Поскольку вы, очевидно, готовы работать с расширенным препроцессором кодом, вы можете попросить DMS выполнить препроцессирование как часть шага преобразования; в него встроены полные препроцессоры GCC4 и GCC4-совместимые препроцессоры.

Как заметили другие, это довольно простой случай, поскольку вы задали работу на уровне полного оператора. Если вы хотите избавить код от любого присваивания, похожего на это утверждение, с такими присваиваниями, встроенными в различные контексты (инициализаторы и т.д.), вам может потребоваться больший набор преобразований для обработки различных специальных случаев, и вам может потребоваться создание других структур кода (например, временных переменных соответствующего типа). Такой инструмент, как DMS, хорош тем, что он может явно вычислить символьный тип для произвольного выражения (тем самым объявив тип всех необходимых временных переменных), и вы можете написать такой больший набор довольно просто и применить их все.

При всем этом, я не уверен в реальной ценности выполнения операции устранения троичного условного выражения. Когда компилятор получит результат, вы можете получить аналогичный объектный код, как если бы вы вообще не делали преобразований. В конце концов, компилятор тоже может применять преобразования, сохраняющие эквивалентность.

Однако, очевидно, есть смысл в регулярных изменениях в целом.

(DMS может применять преобразования программ от исходного текста ко многим языкам, включая C, C++, Java, C# и PHP).

1
ответ дан 18 December 2019 в 09:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: