300456: CF87B. Vasya and Types

Memory Limit:256 MB Time Limit:2 S
Judge Style:Text Compare Creator:
Submit:0 Solved:0

Description

Vasya and Types

题意翻译

程序员 Vasya 正在学习一种新的编程语言 &K*。 &K* 语言在语法上类似于 C 系列语言。但是,它更强大,这就是为什么实际的类 C 语言的规则不适用于它。为了完全理解该语句,请仔细阅读下面的语言描述并遵循它,而不是真正的编程语言中的类似规则。 &K* 上有一个非常强大的指针系统——你可以在现有类型 XX 的右侧添加一个星号——这将产生新的类型 X*X*。这就是所谓的指针定义操作。此外,还有一个相反的操作——对于任何类型的 XX ,它是一个指针,你可以添加一个&符号——这将导致类型 &X ,引用 XX 。这称为取消引用操作。 &K* 语言只有两种基本数据类型——void 和 errtype。此外,该语言具有运算符 typedef 和 typeof。 运算符“typedef AA BB”定义了一个新的数据类型BB,它等价于AA。 AA 可以有星号和与号,而 BB 不能有它们。例如,操作符 typedef void** ptptvoid 将创建一个新类型 ptptvoid,它可以用作 void**。 运算符“typeof AA”返回 AA 的类型,带为 void,即返回类型 void**...*,相当于它带有必要数量的星号(数字可能为零)。也就是说,定义了 ptptvoid 类型后,如上所示,typeof ptptvoid 运算符将返回 void**。 尝试取消引用 void 类型将导致错误:特殊数据类型 errtype。对于 errtype,以下等式成立:errtype* == &errtype == errtype。尝试使用之前未定义的数据类型也会导致 errtype。 使用 typedef,我们可以多次定义一种类型。在所有定义中,只有最后一个是有效的。但是,之前使用此类型定义的所有类型都不会更改。 我们还要注意,解引用操作的优先级低于指针操作,换句话说 &T* 总是等于 TT 。 注意,操作符是一个一个连续执行的。如果我们有两个运算符“typedef &void a”和“typedef a* b”,那么首先 a 变成 errtype,之后 b 变成 errtype* = errtype,但不是 &void* = void(参见示例 2)。 Vasya 还没有完全理解这种强大的技术,这就是他请求你帮助他的原因。编写一个程序来分析这些运算符。

题目描述

Programmer Vasya is studying a new programming language &K\*. The &K\* language resembles the languages of the C family in its syntax. However, it is more powerful, which is why the rules of the actual C-like languages are unapplicable to it. To fully understand the statement, please read the language's description below carefully and follow it and not the similar rules in real programming languages. There is a very powerful system of pointers on &K\* — you can add an asterisk to the right of the existing type $ X $ — that will result in new type $ X* $ . That is called pointer-definition operation. Also, there is the operation that does the opposite — to any type of $ X $ , which is a pointer, you can add an ampersand — that will result in a type $ &X $ , to which refers $ X $ . That is called a dereference operation. The &K\* language has only two basic data types — void and errtype. Also, the language has operators typedef and typeof. - The operator "typedef $ A $ $ B $ " defines a new data type $ B $ , which is equivalent to $ A $ . $ A $ can have asterisks and ampersands, and $ B $ cannot have them. For example, the operator typedef void\*\* ptptvoid will create a new type ptptvoid, that can be used as void\*\*. - The operator "typeof $ A $ " returns type of $ A $ , brought to void, that is, returns the type void\*\*...\*, equivalent to it with the necessary number of asterisks (the number can possibly be zero). That is, having defined the ptptvoid type, as shown above, the typeof ptptvoid operator will return void\*\*. An attempt of dereferencing of the void type will lead to an error: to a special data type errtype. For errtype the following equation holds true: errtype\* $ = $ &errtype $ = $ errtype. An attempt to use the data type that hasn't been defined before that will also lead to the errtype. Using typedef, we can define one type several times. Of all the definitions only the last one is valid. However, all the types that have been defined earlier using this type do not change. Let us also note that the dereference operation has the lower priority that the pointer operation, in other words $ &T* $ is always equal to $ T $ . Note, that the operators are executed consecutively one by one. If we have two operators "typedef &void a" and "typedef a\* b", then at first a becomes errtype, and after that b becomes errtype\* = errtype, but not &void\* = void (see sample 2). Vasya does not yet fully understand this powerful technology, that's why he asked you to help him. Write a program that analyzes these operators.

输入输出格式

输入格式


The first line contains an integer $ n $ ( $ 1<=n<=100 $ ) — the number of operators. Then follow $ n $ lines with operators. Each operator is of one of two types: either "typedef $ A $ $ B $ ", or "typeof $ A $ ". In the first case the $ B $ type differs from void and errtype types, and besides, doesn't have any asterisks and ampersands. All the data type names are non-empty lines of no more than 20 lowercase Latin letters. The number of asterisks and ampersands separately in one type in any operator does not exceed 10, however if we bring some types to void with several asterisks, their number may exceed 10.

输出格式


For every typeof operator print on the single line the answer to that operator — the type that the given operator returned.

输入输出样例

输入样例 #1

5
typedef void* ptv
typeof ptv
typedef &&ptv node
typeof node
typeof &ptv

输出样例 #1

void*
errtype
void

输入样例 #2

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

输出样例 #2

void*
void**
void
void**
errtype
void
errtype
errtype
errtype

说明

Let's look at the second sample. After the first two queries typedef the b type is equivalent to void\*, and с — to void\*\*. The next query typedef redefines b — it is now equal to &b = &void\* = void. At that, the с type doesn't change. After that the с type is defined as &&b\* = &&void\* = &void = errtype. It doesn't influence the b type, that's why the next typedef defines c as &void\* = void. Then the b type is again redefined as &void = errtype. Please note that the c type in the next query is defined exactly as errtype\*\*\*\*\*\*\* = errtype, and not &void\*\*\*\*\*\*\* = void\*\*\*\*\*\*. The same happens in the last typedef.

Input

题意翻译

程序员 Vasya 正在学习一种新的编程语言 &K*。 &K* 语言在语法上类似于 C 系列语言。但是,它更强大,这就是为什么实际的类 C 语言的规则不适用于它。为了完全理解该语句,请仔细阅读下面的语言描述并遵循它,而不是真正的编程语言中的类似规则。 &K* 上有一个非常强大的指针系统——你可以在现有类型 XX 的右侧添加一个星号——这将产生新的类型 X*X*。这就是所谓的指针定义操作。此外,还有一个相反的操作——对于任何类型的 XX ,它是一个指针,你可以添加一个&符号——这将导致类型 &amp;X ,引用 XX 。这称为取消引用操作。 &K* 语言只有两种基本数据类型——void 和 errtype。此外,该语言具有运算符 typedef 和 typeof。 运算符“typedef AA BB”定义了一个新的数据类型BB,它等价于AA。 AA 可以有星号和与号,而 BB 不能有它们。例如,操作符 typedef void** ptptvoid 将创建一个新类型 ptptvoid,它可以用作 void**。 运算符“typeof AA”返回 AA 的类型,带为 void,即返回类型 void**...*,相当于它带有必要数量的星号(数字可能为零)。也就是说,定义了 ptptvoid 类型后,如上所示,typeof ptptvoid 运算符将返回 void**。 尝试取消引用 void 类型将导致错误:特殊数据类型 errtype。对于 errtype,以下等式成立:errtype* == &errtype == errtype。尝试使用之前未定义的数据类型也会导致 errtype。 使用 typedef,我们可以多次定义一种类型。在所有定义中,只有最后一个是有效的。但是,之前使用此类型定义的所有类型都不会更改。 我们还要注意,解引用操作的优先级低于指针操作,换句话说 &amp;T* 总是等于 TT 。 注意,操作符是一个一个连续执行的。如果我们有两个运算符“typedef &void a”和“typedef a* b”,那么首先 a 变成 errtype,之后 b 变成 errtype* = errtype,但不是 &void* = void(参见示例 2)。 Vasya 还没有完全理解这种强大的技术,这就是他请求你帮助他的原因。编写一个程序来分析这些运算符。

加入题单

算法标签: