// <type> ::= <CV-qualifiers> <type> // ::= P <type> # pointer-to // ::= R <type> # reference-to // ::= O <type> # rvalue reference-to (C++0x) // ::= C <type> # complex pair (C 2000) // ::= G <type> # imaginary (C 2000) // ::= U <source-name> <type> # vendor extended type qualifier // ::= <builtin-type> // ::= <function-type> // ::= <class-enum-type> // ::= <array-type> // ::= <pointer-to-member-type> // ::= <template-template-param> <template-args> // ::= <template-param> // ::= <substitution> // ::= Dp <type> # pack expansion of (C++0x) // ::= Dt <expression> E # decltype of an id-expression or class // # member access (C++0x) // ::= DT <expression> E # decltype of an expression (C++0x) // static bool ParseType(State *state) { // We should check CV-qualifers, and PRGC things first. State copy = *state; if (ParseCVQualifiers(state) && ParseType(state)) { return true; } *state = copy; if (ParseCharClass(state, "OPRCG") && ParseType(state)) { return true; } *state = copy; if (ParseTwoCharToken(state, "Dp") && ParseType(state)) { return true; } *state = copy; if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") && ParseExpression(state) && ParseOneCharToken(state, 'E')) { return true; } *state = copy; if (ParseOneCharToken(state, 'U') && ParseSourceName(state) && ParseType(state)) { return true; } *state = copy; if (ParseBuiltinType(state) || ParseFunctionType(state) || ParseClassEnumType(state) || ParseArrayType(state) || ParsePointerToMemberType(state) || ParseSubstitution(state)) { return true; } if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) { return true; } *state = copy; // Less greedy than <template-template-param> <template-args>. if (ParseTemplateParam(state)) { return true; } return false; }
// <expression> ::= <template-param> // ::= <expr-primary> // ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> // ::= <trinary operator-name> <expression> <expression> // <expression> // ::= st <type> // ::= sr <type> <unqualified-name> <template-args> // ::= sr <type> <unqualified-name> static bool ParseExpression(State *state) { if (ParseTemplateParam(state) || ParseExprPrimary(state)) { return true; } State copy = *state; if (ParseOperatorName(state) && ParseExpression(state) && ParseExpression(state) && ParseExpression(state)) { return true; } *state = copy; if (ParseOperatorName(state) && ParseExpression(state) && ParseExpression(state)) { return true; } *state = copy; if (ParseOperatorName(state) && ParseExpression(state)) { return true; } *state = copy; if (ParseTwoChar(state, "st") && ParseType(state)) { return true; } *state = copy; if (ParseTwoChar(state, "sr") && ParseType(state) && ParseUnqualifiedName(state) && ParseTemplateArgs(state)) { return true; } *state = copy; if (ParseTwoChar(state, "sr") && ParseType(state) && ParseUnqualifiedName(state)) { return true; } *state = copy; return false; }
// This part is tricky. If we literally translate them to code, we'll // end up infinite loop. Hence we merge them to avoid the case. // // <prefix> ::= <prefix> <unqualified-name> // ::= <template-prefix> <template-args> // ::= <template-param> // ::= <substitution> // ::= # empty // <template-prefix> ::= <prefix> <(template) unqualified-name> // ::= <template-param> // ::= <substitution> static bool ParsePrefix(State *state) { bool has_something = false; while (true) { MaybeAppendSeparator(state); if (ParseTemplateParam(state) || ParseSubstitution(state) || ParseUnscopedName(state)) { has_something = true; MaybeIncreaseNestLevel(state); continue; } MaybeCancelLastSeparator(state); if (has_something && ParseTemplateArgs(state)) { return ParsePrefix(state); } else { break; } } return true; }
// <template-template-param> ::= <template-param> // ::= <substitution> static bool ParseTemplateTemplateParam(State *state) { return (ParseTemplateParam(state) || ParseSubstitution(state)); }