ANSI Doc No: X3J16/93-0129 ISO Doc No: WG21/N0336 Date: September 24, 1993 Project: Programming Language C++ Ref Doc: Reply To: Eric J. Krohn krohn@bae.bellcore.com +1 908 699-2708 Grammar Rules for Conversion Functions 1. Introduction The C++ grammar in the working paper specifies conversion- function-id such that operator const char * (); is syntactically well formed, but operator const char ** (); is not. Discussion on the c++std-syntax1 and c++std-core2 reflectors indicate that people would like the syntax relaxed to accept the second piece of code. This paper proposes a grammar change to allow this code. 2. The Current Syntax The following are the existing grammar rules relating to conversion-function-id. conversion-function-id: operator conversion-type-id conversion-type-id: type-specifier-seq ptr-operator(opt) ptr-operator: * cv-qualifier-seq(opt) & cv-qualifier-seq(opt) qualified-class-specifier :: * cv-qualifier-seq(opt) __________ 1. Messages 142, 174, 222, 223. 2. Messages 1975, 1976, 1980, 2438, 2442, 2475. September 24, 1993 Page 2 X3J16/93-0129 WG21/N0336 3. Ambiguity Resolution Although Section 12.3.2 (Conversion Functions) says nothing of the parsing ambiguity that is already present with conversion- type-ids, allowing an arbitrary number of ptr-operators after the conversion-function-id makes the ambiguity more obvious. For example, in the presence of a object ac of class type, this code &ac.operator int * * p; can be parsed as either &(ac.operator int) * (* p); or &(ac.operator int *) * (p); With an arbitrary number of asterisks allowed in a conversion- type-id, the problem becomes worse. The existing grammar rules have two shift/reduce conflicts caused by conversion-type-id. shift/reduce conflict (shift 2, reduce 429) on '&' shift/reduce conflict (shift 4, reduce 429) on '*' conversion_type_id : type_specifier_seq . ptr_operator (428) conversion_type_id : type_specifier_seq . (429) $start OPERATOR CLASS_NAME . '&' (1 reduction, or a shift) $start OPERATOR CLASS_NAME . '*' (1 reduction, or a shift) The specific grammar rules proposed in the next section introduce two additional shift/reduce conflicts. shift/reduce conflict (shift 2, reduce 552) on '&' shift/reduce conflict (shift 4, reduce 552) on '*' conversion_declarator : ptr_operator . conversion_declarator (551) conversion_declarator : ptr_operator . (552) $start OPERATOR CLASS_NAME '*' . '&' (1 reduction, or a shift) $start OPERATOR CLASS_NAME '*' . '*' (1 reduction, or a shift) These correspond to existing shift/reduce conflicts with new- type-id. For new-type-id we use the so-called "maximal munch" rule to resolve a similar ambiguity. I propose we adopt similar wording for conversion-function-id. 4. Proposal I propose allowing an arbitrary number of ptr-operators after the type-specifier-seq. Change conversion-type-id from conversion-type-id: type-specifier-seq ptr-operator(opt) to September 24, 1993 Page 3 X3J16/93-0129 WG21/N0336 conversion-type-id: type-specifier-seq conversion-declarator(opt) conversion-declarator: ptr-operator conversion-declarator(opt) Add a paragraph to Section 12.3.2 (Conversion Functions) worded much the same as 5.3.3p11: The conversion-type-id in a conversion-function-id is the longest possible sequence of conversion-declaratorss. This prevents ambiguities between declarator operator * and its expression counterparts. For example, &ac.operator int*i; // syntax error: parsed as `&(ac.operator int*) i' // not as `&(ac.operator int)*i' The * is the pointer declarator and not the multiplication operator. 5. Alternatives We could instead change conversion-type-id from conversion-type-id: type-specifier-seq ptr-operator(opt) to conversion-type-id: type-specifier-seq conversion-type-id ptr-operator This formulation avoids the extra two shift/reduce conflicts but it does not follow the pattern of declarator, abstract- declarator, and new-declarator, and so is not proposed.