private SyntaxNode ParseFunctionDefinitionOrDeclaration(bool declarationOnly)
{
var attributes = ParseAttributes();
var modifiers = new List<SyntaxToken>();
ParseDeclarationModifiers(modifiers);
var returnType = ParseReturnType();
var name = ParseDeclarationName(declarationOnly);
var openParen = Match(SyntaxKind.OpenParenToken);
var parameters = new List<SyntaxNode>();
while (Current.Kind != SyntaxKind.CloseParenToken)
{
if (IsPossibleParameter())
{
parameters.Add(ParseParameter());
if (Current.Kind != SyntaxKind.CloseParenToken)
{
if (Current.Kind == SyntaxKind.CommaToken)
{
parameters.Add(Match(SyntaxKind.CommaToken));
}
else
{
var action = SkipBadTokens(
p => p.Current.Kind != SyntaxKind.CommaToken,
p => p.IsTerminator() || p.Current.Kind == SyntaxKind.OpenParenToken,
SyntaxKind.CommaToken);
if (action == PostSkipAction.Abort)
break;
}
}
}
else
{
var action = SkipBadTokens(
p => !p.IsPossibleParameter(),
p => p.IsTerminator() || p.Current.Kind == SyntaxKind.OpenParenToken,
SyntaxKind.CloseParenToken);
if (action == PostSkipAction.Abort)
break;
}
}
var closeParen = Match(SyntaxKind.CloseParenToken);
SemanticSyntax semantic = null;
if (Current.Kind == SyntaxKind.ColonToken)
semantic = ParseSemantic();
if (!declarationOnly && (name.Kind == SyntaxKind.QualifiedDeclarationName || Current.Kind == SyntaxKind.OpenBraceToken))
{
var body = ParseBlock(new List<AttributeSyntax>());
var semicolon = NextTokenIf(SyntaxKind.SemiToken);
return new FunctionDefinitionSyntax(attributes, modifiers, returnType,
name, new ParameterListSyntax(openParen, new SeparatedSyntaxList<ParameterSyntax>(parameters), closeParen),
semantic, body, semicolon);
}
else
{
var semicolon = Match(SyntaxKind.SemiToken);
Debug.Assert(name.Kind == SyntaxKind.IdentifierDeclarationName);
return new FunctionDeclarationSyntax(attributes, modifiers, returnType, name,
new ParameterListSyntax(openParen, new SeparatedSyntaxList<ParameterSyntax>(parameters), closeParen),
semantic, semicolon);
}
}