// <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));
}
Exemple #5
0
/* 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;
}