@@ -4494,6 +4494,10 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes) {
4494
4494
return Tok.is (tok::identifier);
4495
4495
}
4496
4496
4497
+ // 'macro' name
4498
+ if (Tok.isContextualKeyword (" macro" ) && Tok2.is (tok::identifier))
4499
+ return true ;
4500
+
4497
4501
// If the next token is obviously not the start of a decl, bail early.
4498
4502
if (!isKeywordPossibleDeclStart (Tok2))
4499
4503
return false ;
@@ -4824,6 +4828,12 @@ Parser::parseDecl(ParseDeclOptions Flags,
4824
4828
break ;
4825
4829
}
4826
4830
4831
+ if (Tok.isContextualKeyword (" macro" ) && peekToken ().is (tok::identifier)) {
4832
+ Tok.setKind (tok::contextual_keyword);
4833
+ DeclResult = parseDeclMacro (Attributes);
4834
+ break ;
4835
+ }
4836
+
4827
4837
if (Flags.contains (PD_HasContainerType) &&
4828
4838
IsAtStartOfLineOrPreviousHadSemi) {
4829
4839
@@ -8976,6 +8986,127 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
8976
8986
return makeParserResult (result);
8977
8987
}
8978
8988
8989
+ ParserResult<MacroDecl> Parser::parseDeclMacro (DeclAttributes &Attributes) {
8990
+ assert (Tok.isContextualKeyword (" macro" ));
8991
+ SourceLoc macroLoc = consumeToken (); // 'macro'
8992
+
8993
+ Identifier macroName;
8994
+ SourceLoc macroNameLoc;
8995
+ ParserStatus status;
8996
+
8997
+ status |= parseIdentifierDeclName (
8998
+ *this , macroName, macroNameLoc, " macro" ,
8999
+ [&](const Token &next) {
9000
+ return next.isAny (tok::colon, tok::l_paren) || startsWithLess (next);
9001
+ });
9002
+ if (status.isErrorOrHasCompletion ())
9003
+ return status;
9004
+
9005
+ DebuggerContextChange dcc (*this , macroName, DeclKind::Macro);
9006
+
9007
+ // Parse the generic-params, if present.
9008
+ GenericParamList *genericParams = nullptr ;
9009
+ {
9010
+ auto result = maybeParseGenericParams ();
9011
+ genericParams = result.getPtrOrNull ();
9012
+ if (result.hasCodeCompletion ())
9013
+ return makeParserCodeCompletionStatus ();
9014
+ }
9015
+
9016
+ // Parse the macro signature.
9017
+ TypeRepr *resultType = nullptr ;
9018
+ ParameterList *parameterList = nullptr ;
9019
+ DeclName macroFullName;
9020
+ if (consumeIf (tok::colon)) {
9021
+ // Value-like macros.
9022
+ auto type = parseType (diag::expected_macro_value_type);
9023
+ status |= type;
9024
+ if (status.isErrorOrHasCompletion ())
9025
+ return status;
9026
+
9027
+ resultType = type.getPtrOrNull ();
9028
+ macroFullName = macroName;
9029
+ } else {
9030
+ // Parameter list.
9031
+ SmallVector<Identifier, 2 > namePieces;
9032
+ DefaultArgumentInfo defaultArgs;
9033
+ auto parameterResult = parseSingleParameterClause (
9034
+ ParameterContextKind::Macro, &namePieces, &defaultArgs);
9035
+ status |= parameterResult;
9036
+ parameterList = parameterResult.getPtrOrNull ();
9037
+
9038
+ // ->
9039
+ SourceLoc arrowLoc;
9040
+ if (!consumeIf (tok::arrow, arrowLoc)) {
9041
+ diagnose (Tok, diag::macro_decl_expected_arrow);
9042
+ }
9043
+
9044
+ // Result type.
9045
+ auto parsedResultType =
9046
+ parseDeclResultType (diag::expected_type_macro_result);
9047
+ resultType = parsedResultType.getPtrOrNull ();
9048
+ status |= parsedResultType;
9049
+ if (status.isErrorOrHasCompletion ())
9050
+ return status;
9051
+
9052
+ macroFullName = DeclName (Context, macroName, namePieces);
9053
+ }
9054
+
9055
+ // Parse '=' ModuleName . MacroTypeName
9056
+ if (!consumeIf (tok::equal)) {
9057
+ diagnose (Tok, diag::macro_decl_expected_equal);
9058
+ }
9059
+
9060
+ // ModuleName
9061
+ Identifier externalMacroModule;
9062
+ SourceLoc externalMacroModuleLoc;
9063
+ status |= parseIdentifierDeclName (
9064
+ *this , externalMacroModule, externalMacroModuleLoc,
9065
+ " external macro module" ,
9066
+ [&](const Token &next) {
9067
+ return next.is (tok::period);
9068
+ });
9069
+ if (status.isErrorOrHasCompletion ())
9070
+ return status;
9071
+
9072
+ // '.'
9073
+ if (!consumeIf (tok::period)) {
9074
+ diagnose (Tok, diag::macro_decl_expected_period);
9075
+ }
9076
+
9077
+ // MacroTypeName
9078
+ Identifier externalMacroTypeName;
9079
+ SourceLoc externalMacroTypeNameLoc;
9080
+ status |= parseIdentifierDeclName (
9081
+ *this , externalMacroTypeName, externalMacroTypeNameLoc,
9082
+ " external macro type name" ,
9083
+ [&](const Token &next) {
9084
+ return true ;
9085
+ });
9086
+ if (status.isErrorOrHasCompletion ())
9087
+ return status;
9088
+
9089
+ // Create the macro declaration.
9090
+ auto *macro = new (Context) MacroDecl (
9091
+ MacroDecl::Kind::Expression, MacroDecl::ImplementationKind::Builtin,
9092
+ macroName, CurDeclContext->getParentModule (), { }, nullptr );
9093
+
9094
+ // FIXME: Egregious hack.
9095
+ macro->setImplicit ();
9096
+
9097
+ // Parse a 'where' clause if present.
9098
+ if (Tok.is (tok::kw_where)) {
9099
+ auto whereStatus = parseFreestandingGenericWhereClause (macro);
9100
+ if (whereStatus.hasCodeCompletion () && !CodeCompletion) {
9101
+ // Trigger delayed parsing, no need to continue.
9102
+ return whereStatus;
9103
+ }
9104
+ status |= whereStatus;
9105
+ }
9106
+
9107
+ return dcc.fixupParserResult (status, macro);
9108
+ }
9109
+
8979
9110
ParserResult<MacroExpansionDecl>
8980
9111
Parser::parseDeclMacroExpansion (ParseDeclOptions flags,
8981
9112
DeclAttributes &attributes) {
0 commit comments