// trailer: '(' [ arglist_genexpr ] ')' | '[' subscriptlist ']' | '.' NAME private Expression AddTrailers(Expression ret, bool allowGeneratorExpression) { bool prevAllow = _allowIncomplete; try { _allowIncomplete = true; while (true) { switch (PeekToken().Kind) { case TokenKind.LeftParenthesis: if (!allowGeneratorExpression) return ret; NextToken(); Arg[] args = FinishArgListOrGenExpr(); CallExpression call; if (args != null) { call = FinishCallExpr(ret, args); } else { call = new CallExpression(ret, new Arg[0]); } call.SetLoc(_globalParent, ret.StartIndex, GetEnd()); ret = call; break; case TokenKind.LeftBracket: NextToken(); Expression index = ParseSubscriptList(); IndexExpression ie = new IndexExpression(ret, index); ie.SetLoc(_globalParent, ret.StartIndex, GetEnd()); ret = ie; break; case TokenKind.Dot: NextToken(); string name = ReadNameMaybeNone(); MemberExpression fe = new MemberExpression(ret, name); fe.SetLoc(_globalParent, ret.StartIndex, GetEnd()); ret = fe; break; case TokenKind.Constant: // abc.1, abc"", abc 1L, abc 0j ReportSyntaxError("invalid syntax"); return Error(); default: return ret; } } } finally { _allowIncomplete = prevAllow; } }
// decorators ::= // decorator+ // decorator ::= // "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE private List<Expression> ParseDecorators() { List<Expression> decorators = new List<Expression>(); while (MaybeEat(TokenKind.At)) { var start = GetStart(); Expression decorator = new NameExpression(ReadName()); decorator.SetLoc(_globalParent, start, GetEnd()); while (MaybeEat(TokenKind.Dot)) { string name = ReadNameMaybeNone(); decorator = new MemberExpression(decorator, name); decorator.SetLoc(_globalParent, GetStart(), GetEnd()); } decorator.SetLoc(_globalParent, start, GetEnd()); if (MaybeEat(TokenKind.LeftParenthesis)) { if (_sink != null) { _sink.StartParameters(GetSourceSpan()); } Arg[] args = FinishArgumentList(null); decorator = FinishCallExpr(decorator, args); } decorator.SetLoc(_globalParent, start, GetEnd()); EatNewLine(); decorators.Add(decorator); } return decorators; }