Codeforces Beta Round 73 (Div. 1 Only) |
---|
Закончено |
Программист Вася изучает новый язык программирования &K*. Язык &K* по своему синтаксису напоминает языки семейства C, однако он гораздо более мощный, и поэтому правила реальных C-подобных языков к нему не применимы. Для полного понимания условия внимательно прочитайте описание языка ниже, и следуйте ему, а не аналогичным правилам в реальных языках программирования.
В &K* есть очень мощная технология указателей — к имеющемуся типу X можно приписать звездочку после него и получить тип X * . Это называется операцией взятия указателя. А есть противоположная операция — к любому типу X, являющемуся указателем, можно приписать слева амперсанд и получить тип &X, на который ссылается X. Это называется операцией разыменовывания.
В языке &K* есть только два базовых типа данных — void и errtype. Также в этом языке есть операторы typedef и typeof.
Попытка разыменовать тип void приводит к ошибке: особому типу данных errtype. Для errtype верно следующее соотношение: errtype* = &errtype = errtype. Попытка использовать не объявленный ранее тип данных так же приведет к типу errtype.
С помощью typedef можно определить один тип несколько раз. Из всех определений силу имеет только последнее. Однако все типы, которые были определены с его использованием ранее, не меняются.
Заметим также, что операция разыменовывания имеет меньший приоритет, чем операция взятия указателя, иными словами &T * всегда равно T.
Учтите, что операторы выполняются последовательно, один за другим. Пусть у нас есть два оператора "typedef &void a" и "typedef a* b". Сначала a принимает значение errtype, а затем b принимает значение errtype* = errtype, но не &void* = void (см. пример 2).
Вася еще не до конца понимает эту мощную технологию, поэтому он попросил вас помочь в ней разобраться. Напишите программу, которая обрабатывает эти операторы и операции.
В первой строке находится целое число n (1 ≤ n ≤ 100) — количество операторов. Далее идет n строк с операторами. Каждый оператор имеет один из двух видов: либо "typedef A B", либо "typeof A". В первом случае тип B отличается от типов void и errtype, а так же не содержит звездочек и амперсандов.
Все названия типов данных — непустые строки из не более чем 20 строчных латинских букв. Количество звездочек и амперсандов по отдельности при одном типе в любом операторе не превышает 10, однако при приведении некоторых типов к void c несколькими звездочками, их количество может превысить 10.
На каждый оператор typeof выведите в отдельной строке ответ на этот оператор — тип, который вернул данный оператор.
5
typedef void* ptv
typeof ptv
typedef &&ptv node
typeof node
typeof &ptv
void*
errtype
void
17
typedef void* b
typedef b* c
typeof b
typeof c
typedef &b b
typeof b
typeof c
typedef &&b* c
typeof c
typedef &b* c
typeof c
typedef &void b
typeof b
typedef b******* c
typeof c
typedef &&b* c
typeof c
void*
void**
void
void**
errtype
void
errtype
errtype
errtype
Разберем второй пример.
После первых двух запросов typedef тип b эквивалентен void*, а с — void**.
Следующий запрос typedef переопределяет b — теперь он равен &b = &void* = void. Тип с при этом не меняется.
После чего тип с определяется как &&b* = &&void* = &void = errtype. На тип b это никак не влияет, поэтому следующий typedef определяет c, как &void* = void.
Далее тип b снова переопределяется как &void = errtype.
Отметим, что тип c в следующем запросе определяется именно как errtype******* = errtype, а не &void******* = void******. Тоже самое происходит и в последнем typedef.
Название |
---|