// parameter ::= // identifier | "(" sublist ")" private Parameter ParseParameter(int position, HashSet<string> names, ParameterKind kind, bool isTyped = false) { Name name; Parameter parameter; if (PeekToken().Kind == TokenKind.LeftParenthesis) { // sublist string parenWhiteSpace = _lookaheadWhiteSpace; NextToken(); var parenStart = GetStart(); Expression ret = ParseSublist(names, true); if (_langVersion.Is3x()) { ReportSyntaxError(parenStart, GetEnd(), "sublist parameters are not supported in 3.x"); } bool ateRightParen = Eat(TokenKind.RightParenthesis); string closeParenWhiteSpace = _tokenWhiteSpace; TupleExpression tret = ret as TupleExpression; NameExpression nameRet; if (tret != null) { parameter = new SublistParameter(position, tret); if (_verbatim) { AddPreceedingWhiteSpace(tret, parenWhiteSpace); AddSecondPreceedingWhiteSpace(tret, closeParenWhiteSpace); if (!ateRightParen) { AddErrorMissingCloseGrouping(parameter); } } } else if ((nameRet = ret as NameExpression) != null) { parameter = new Parameter(nameRet.Name, kind); if (_verbatim) { AddThirdPreceedingWhiteSpace(parameter, (string)_attributes[nameRet][NodeAttributes.PreceedingWhiteSpace]); AddIsAltForm(parameter); if (!ateRightParen) { AddErrorMissingCloseGrouping(parameter); } } } else { Debug.Assert(ret is ErrorExpression); ReportSyntaxError(_lookahead); parameter = new ErrorParameter((ErrorExpression)ret); AddIsAltForm(parameter); } if (parameter != null) { parameter.SetLoc(ret.IndexSpan); } if (_verbatim) { AddPreceedingWhiteSpace(parameter, parenWhiteSpace); AddSecondPreceedingWhiteSpace(parameter, closeParenWhiteSpace); if (!ateRightParen) { AddErrorMissingCloseGrouping(parameter); } } } else if ((name = TokenToName(PeekToken())).HasName) { NextToken(); var paramStart = GetStart(); parameter = new Parameter(name.RealName, kind); if (_verbatim) { AddPreceedingWhiteSpace(parameter, _tokenWhiteSpace); AddVerbatimName(name, parameter); } if (isTyped && MaybeEat(TokenKind.Colon)) { if (_verbatim) { AddThirdPreceedingWhiteSpace(parameter, _tokenWhiteSpace); } var start = GetStart(); parameter.Annotation = ParseExpression(); if (_langVersion.Is2x()) { ReportSyntaxError(start, parameter.Annotation.EndIndex, "invalid syntax, parameter annotations require 3.x"); } } CompleteParameterName(parameter, name.RealName, names, paramStart); } else { ReportSyntaxError(_lookahead); NextToken(); parameter = new ErrorParameter(_verbatim ? Error(_tokenWhiteSpace + _token.Token.VerbatimImage) : null); } return parameter; }
//varargslist: (fpdef ['=' expression ] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | fpdef ['=' expression] (',' fpdef ['=' expression])* [','] //fpdef: NAME | '(' fplist ')' //fplist: fpdef (',' fpdef)* [','] private Parameter[] ParseVarArgsList(TokenKind terminator, out List<string> commaWhiteSpace, out bool ateTerminator, bool isTyped = false) { // parameters not doing * or ** today List<Parameter> pl = new List<Parameter>(); commaWhiteSpace = MakeWhiteSpaceList(); HashSet<string> names = new HashSet<string>(StringComparer.Ordinal); bool needDefault = false, parsedStarArgs = false; string namedOnlyText = null; for (int position = 0; ; position++) { if (MaybeEat(terminator)) { ateTerminator = true; break; } Parameter parameter; var lookahead = _lookahead; if (MaybeEat(TokenKind.Multiply)) { string starWhiteSpace = _tokenWhiteSpace; if (parsedStarArgs) { ReportSyntaxError(lookahead.Span.Start, GetEnd(), "duplicate * args arguments"); } parsedStarArgs = true; if (_langVersion.Is3x()) { if (MaybeEat(TokenKind.Comma)) { string namedOnlyWhiteSpace = _tokenWhiteSpace; // bare * if (MaybeEat(terminator)) { ReportSyntaxError(lookahead.Span.Start, GetEnd(), "named arguments must follow bare *"); ateTerminator = true; break; } if (_verbatim) { namedOnlyText = starWhiteSpace + "*" + namedOnlyWhiteSpace + ","; } continue; } } parameter = ParseParameterName(names, ParameterKind.List, isTyped); if (parameter == null) { // no parameter name, syntax error parameter = new ErrorParameter(Error(starWhiteSpace + "*" + _lookaheadWhiteSpace + _lookahead.Token.VerbatimImage)); NextToken(); } else if (_verbatim) { AddPreceedingWhiteSpace(parameter, starWhiteSpace); } if (namedOnlyText != null) { if (_verbatim) { AddExtraVerbatimText(parameter, namedOnlyText); } namedOnlyText = null; } pl.Add(parameter); if (!MaybeEat(TokenKind.Comma)) { ateTerminator = Eat(terminator); break; } if (commaWhiteSpace != null) { commaWhiteSpace.Add(_tokenWhiteSpace); } continue; } else if (MaybeEat(TokenKind.Power)) { string starStarWhiteSpace = _tokenWhiteSpace; parameter = ParseParameterName(names, ParameterKind.Dictionary, isTyped); if (parameter == null) { // no parameter name, syntax error parameter = new ErrorParameter(Error(starStarWhiteSpace + "**" + _lookaheadWhiteSpace + _lookahead.Token.VerbatimImage)); NextToken(); } pl.Add(parameter); if (_verbatim) { AddPreceedingWhiteSpace(parameter, starStarWhiteSpace); } ateTerminator = Eat(terminator); if (namedOnlyText != null) { if (_verbatim) { AddExtraVerbatimText(parameter, namedOnlyText); } namedOnlyText = null; } break; } // // Parsing defparameter: // // defparameter ::= // parameter ["=" expression] parameter = ParseParameter(position, names, parsedStarArgs ? ParameterKind.KeywordOnly : ParameterKind.Normal, isTyped); pl.Add(parameter); if (MaybeEat(TokenKind.Assign)) { if (_verbatim) { AddSecondPreceedingWhiteSpace(parameter, _tokenWhiteSpace); } needDefault = true; parameter.DefaultValue = ParseExpression(); parameter.EndIndex = parameter.DefaultValue.EndIndex; } else if (needDefault && !parsedStarArgs) { ReportSyntaxError(parameter.StartIndex, parameter.EndIndex, "default value must be specified here"); } if (namedOnlyText != null) { if (_verbatim) { AddExtraVerbatimText(parameter, namedOnlyText); } namedOnlyText = null; } if (parsedStarArgs && _langVersion.Is2x()) { ReportSyntaxError(parameter.StartIndex, GetEnd(), "positional parameter after * args not allowed"); } if (!MaybeEat(TokenKind.Comma)) { ateTerminator = Eat(terminator); break; } if (commaWhiteSpace != null) { commaWhiteSpace.Add(_tokenWhiteSpace); } } return pl.ToArray(); }