// Parse a type template parameter. // // type-template-parameter: // typename [identifier] ['='' type] // // Note that the point of declaration for a template parameter is // past the full definition (after the default argument, if present). Decl& Parser::type_template_parameter() { match(tk::typename_tok); // Get the optional identifier. Create a placeholder // if no name is given. Name* n; if (Token id = match_if(tk::identifier_tok)) n = &on_simple_id(id); else n = &build.get_id(); // Parse the default argument. Type* t = nullptr; if (lookahead() == tk::eq_tok) t = &type(); // Point of declaration. Decl* d; if (t) d = &on_type_template_parameter(*n, *t); else d = &on_type_template_parameter(*n); return *d; }
// Parse an unqualified-id. // // unqualified-id: // identifier // operator-id // conversion-id // literal-id // destructor-id // template-id // concept-id // // TODO: Support operator, conversion, and literal ids. Note that // all of those begin with 'operator', but can be syntactically // differentiated by lookahead(1). Operator-ids are followed by // an operator symbol, literal id's are followed by an empty string // literal, and conversion id's are the rest. // // FIXME: Finish implementing me. Note that the interpretation of // an identifier depends on both lookup and context. Name& Parser::unqualified_id() { if (lookahead() == tilde_tok) return destructor_id(); // Use a trial parser to determine if we're looking at a template-id // or concept-id instead of a plain old identifier. // // FIXME: This doesn't really need to be a trial parse. Just get // the identifier, and depending on a) its resolution and b) whether // we assume it should be interpreted as a template or concept via // a prior keyword, handle the template argument. if (Name* n = match_if(&Parser::template_id)) return *n; if (Name* n = match_if(&Parser::concept_id)) return *n; Token tok = match(identifier_tok); return on_simple_id(tok); }