// <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; }
// 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; }
// <unscoped-template-name> ::= <unscoped-name> // ::= <substitution> static bool ParseUnscopedTemplateName(State *state) { return ParseUnscopedName(state) || ParseSubstitution(state); }
// <template-template-param> ::= <template-param> // ::= <substitution> static bool ParseTemplateTemplateParam(State *state) { return (ParseTemplateParam(state) || ParseSubstitution(state)); }
/* Parse the next expression */ VyParseTree* Parse(){ /* Check that we have not reached the end of the input stream; if so, return null */ if(!MoreTokensExist()){ return NULL; } /* Get the next token */ VyToken* next = GetNextToken(); /* It's type is used to determine how to continue parsing */ int tokType = next->type; /* Store the result of parsing before returning it */ VyParseTree* expr; /* If it starts with a parenthesis, parse it as a list */ if(tokType == OPAREN){ expr = ParseList(); } /* If it begins with a quote, then parse whatever is next and quote it */ else if(tokType == QUOTE){ expr = ParseQuoted(); } /* Parse a substitution */ else if(tokType == DOLLAR){ expr = ParseSubstitution(); } /* Parse a splicing substitution */ else if(tokType == DOLLARAT){ expr = ParseSpliceSubstitution(); } /* Parse a bracketed list */ else if(tokType == OBRACKET){ expr = ParseBracketedList(); } /* Parse an infix list (curly braces) */ else if(tokType == OCURLY){ expr = ParseCurlyList(); } /* If it is a number, identifier, or string then make a parse tree out of the token */ else if(tokType == IDENT){ VyParseTree* ident = MakeIdent(); SetStrData(ident, next->data); expr = ident; } else if(tokType == NUM){ expr = ParseNumberFromToken(next); } else if(tokType == STRING){ VyParseTree* str = MakeString(); SetStrData(str,next->data); expr = str; } /* Unexpected end of list */ else if(tokType == CPAREN || tokType == CBRACKET || tokType == CCURLY){ VyParseTree* err = ParseError("Unexpected end of list"); SetPosition(err, next->pos); return err; } /* If there is no expression before a :, then the token type will be COLON * Instead of dying, add an error */ else if(tokType == COLON){ VyParseTree* error = ParseError("Reference lacking instance"); SetPosition(error, next->pos); return error; } /* Handle object references: Check whether the next token is a colon. * If so, then use the previously parsed expression (expr) and another * expression gotten from Parse() to create a reference node */ VyToken* lookAhead = GetNextToken(); if(lookAhead != NULL /* Make sure that the token list didn't end before looking at the type */ && lookAhead->type == COLON){ VyParseTree* obj = expr; VyParseTree* ref = Parse(); /* Check for validity */ if(ref == NULL){ expr = Reference(obj, ParseError("Incomplete reference.")); }else{ expr = Reference(obj, ref); } } else{ /* Backtrack one token to make up for the lookahead */ if(lookAhead != NULL) BacktrackToken(); } /* Set the position of the current expression */ SetPosition(expr, next->pos); /* If the tree is an object reference, set the position of * the first part (obj), because it wasn't gotten through a full Parse() call*/ if(expr->type == TREE_REF){ SetPosition(GetObj(expr), next->pos); } return expr; }