Files
swift-mirror/lib/Parse/ParseGeneric.cpp
Doug Gregor ec31aaf04b Parse a generic parameter list within a function declaration, and
introduce the generic type parameters (which are simply type aliases
for a to-be-determined archetype type) into scope for name
lookup. We can now parse something like

  func f<T, U : Range>(x : T, y : U) { }

but there is no semantic analysis or even basic safety checking (yet).




Swift SVN r2197
2012-06-18 22:49:54 +00:00

105 lines
3.0 KiB
C++

//===--- ParseGeneric.cpp - Swift Language Parser for Generics ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Generic Parsing and AST Building
//
//===----------------------------------------------------------------------===//
#include "Parser.h"
#include "swift/AST/Diagnostics.h"
#include "swift/Parse/Lexer.h"
using namespace swift;
/// parseGenericParameters - Parse a sequence of generic parameters, e.g.,
/// < T : Comparable, U : Container>
///
/// generic-params:
/// '<' generic-param (',' generic-param)? '>'
///
/// generic-param:
/// identifier
/// identifier ':' type-identifier
/// identifier ':' type-composition
bool
Parser::parseGenericParameters(SmallVectorImpl<GenericParam> &GenericParams) {
// Parse the opening '<'.
assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
SourceLoc LAngleLoc = consumeStartingLess();
// Parse the generic parameter list.
bool Invalid = false;
while (true) {
// Parse the name of the parameter.
Identifier Name;
SourceLoc NameLoc = Tok.getLoc();
if (parseIdentifier(Name, diag::expected_generics_parameter_name)) {
Invalid = true;
break;
}
// Parse the ':' followed by a type.
SmallVector<Type, 1> Inherited;
if (Tok.is(tok::colon)) {
(void)consumeToken();
Type Ty;
TypeLoc *TyLoc = nullptr;
if (Tok.getKind() == tok::identifier) {
parseTypeIdentifier(Ty, TyLoc);
} else if (Tok.getKind() == tok::kw_protocol) {
parseTypeComposition(Ty, TyLoc);
} else {
diagnose(Tok.getLoc(), diag::expected_generics_type_restriction, Name);
Invalid = true;
}
if (Ty)
Inherited.push_back(Ty);
}
// FIXME: Bad location info here
TypeAliasDecl *Param
= new (Context) TypeAliasDecl(NameLoc, Name, NameLoc, Type(),
CurDeclContext,
Context.AllocateCopy(Inherited));
GenericParams.push_back(Param);
// Parse the comma, if the list continues.
if (Tok.is(tok::comma)) {
consumeToken();
continue;
}
break;
}
// Parse the closing '>'.
SourceLoc RAngleLoc;
if (!startsWithGreater(Tok)) {
if (!Invalid) {
diagnose(Tok.getLoc(), diag::expected_rangle_generics_param);
diagnose(LAngleLoc, diag::opening_angle);
Invalid = true;
}
// Skip until we hit the '>'.
skipUntilAnyOperator();
if (startsWithGreater(Tok))
RAngleLoc = consumeStartingGreater();
else
RAngleLoc = Tok.getLoc();
} else {
RAngleLoc = consumeStartingGreater();
}
return Invalid;
}