//subscriptlist: subscript (',' subscript)* [','] //subscript: '.' '.' '.' | expression | [expression] ':' [expression] [sliceop] //sliceop: ':' [expression] private Expression ParseSubscriptList() { const TokenKind terminator = TokenKind.RightBracket; var start0 = GetStart(); bool trailingComma = false; List<Expression> l = new List<Expression>(); while (true) { Expression e; if (MaybeEat(TokenKind.Dot)) { var start = GetStart(); Eat(TokenKind.Dot); Eat(TokenKind.Dot); e = new ConstantExpression(Ellipsis.Value); e.SetLoc(_globalParent, start, GetEnd()); } else if (MaybeEat(TokenKind.Colon)) { e = FinishSlice(null, GetStart()); } else { e = ParseExpression(); if (MaybeEat(TokenKind.Colon)) { e = FinishSlice(e, e.StartIndex); } } l.Add(e); if (!MaybeEat(TokenKind.Comma)) { Eat(terminator); trailingComma = false; break; } trailingComma = true; if (MaybeEat(terminator)) { break; } } Expression ret = MakeTupleOrExpr(l, trailingComma, true); ret.SetLoc(_globalParent, start0, GetEnd()); return ret; }
/// <summary> /// Peek if the next token is a 'yield' and parse a yield expression. Else return null. /// /// Called w/ yield already eaten. /// </summary> /// <returns>A yield expression if present, else null. </returns> // yield_expression: "yield" [expression_list] private Expression ParseYieldExpression() { // Mark that this function is actually a generator. // If we're in a generator expression, then we don't have a function yet. // g=((yield i) for i in range(5)) // In that acse, the genexp will mark IsGenerator. FunctionDefinition current = CurrentFunction; if (current != null) { current.IsGenerator = true; } var start = GetStart(); // Parse expression list after yield. This can be: // 1) empty, in which case it becomes 'yield None' // 2) a single expression // 3) multiple expression, in which case it's wrapped in a tuple. Expression yieldResult; bool trailingComma; List<Expression> l = ParseExpressionList(out trailingComma); if (l.Count == 0) { // Check empty expression and convert to 'none' yieldResult = new ConstantExpression(null); // location set to match yield location (consistent with cpython) yieldResult.SetLoc(_globalParent, start, GetEnd()); } else if (l.Count != 1) { // make a tuple yieldResult = MakeTupleOrExpr(l, trailingComma); } else { // just take the single expression yieldResult = l[0]; } Expression yieldExpression = new YieldExpression(yieldResult); yieldExpression.SetLoc(_globalParent, start, GetEnd()); return yieldExpression; }
// primary: atom | attributeref | subscription | slicing | call // atom: identifier | literal | enclosure // enclosure: // parenth_form | // list_display | // generator_expression | // dict_display | // string_conversion | // yield_atom private Expression ParsePrimary() { Token t = PeekToken(); Expression ret; switch (t.Kind) { case TokenKind.LeftParenthesis: // parenth_form, generator_expression, yield_atom NextToken(); return FinishTupleOrGenExp(); case TokenKind.LeftBracket: // list_display NextToken(); return FinishListValue(); case TokenKind.LeftBrace: // dict_display NextToken(); return FinishDictValue(); case TokenKind.BackQuote: // string_conversion NextToken(); return FinishStringConversion(); case TokenKind.Name: // identifier NextToken(); SourceSpan span = GetSpan(); string name = (string)t.Value; _sink.StartName(span, name); ret = new NameExpression(FixName(name)); ret.SetLoc(GetStart(), GetEnd()); return ret; case TokenKind.Constant: // literal NextToken(); SourceLocation start = GetStart(); object cv = t.Value; string cvs = cv as string; if (cvs != null) { cv = FinishStringPlus(cvs); } else { Bytes bytes = cv as Bytes; if (bytes != null) { cv = FinishBytesPlus(bytes); } } ret = new ConstantExpression(cv); ret.SetLoc(start, GetEnd()); return ret; default: ReportSyntaxError(_lookahead.Token, _lookahead.Span, ErrorCodes.SyntaxError, _allowIncomplete || _tokenizer.EndContinues); // error node ret = new ErrorExpression(); ret.SetLoc(_lookahead.Span.Start, _lookahead.Span.End); return ret; } }
// atom: '(' [testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+ private Expression ParsePrimary() { Token t = NextToken(); Expression ret; switch (t.Kind) { case TokenKind.LeftParenthesis: return FinishTupleOrGenExp(); case TokenKind.LeftBracket: return FinishListValue(); case TokenKind.LeftBrace: return FinishDictValue(); case TokenKind.BackQuote: return FinishBackquote(); case TokenKind.Name: CodeSpan span = GetSpan(); SymbolId name = (SymbolId)t.Value; context.Sink.StartName(span, name.GetString()); ret = new NameExpression(FixName(name)); ret.SetLoc(GetExternal(), GetStart(), GetEnd()); return ret; case TokenKind.Constant: Location start = GetStart(); object cv = t.Value; if (cv is String) { cv = FinishStringPlus((string)cv); } // todo handle STRING+ ret = new ConstantExpression(cv); ret.SetLoc(GetExternal(), start, GetEnd()); return ret; default: ReportSyntaxError(t, ErrorCodes.SyntaxError, allowingIncomplete); // error node ret = new ErrorExpression(); ret.SetLoc(GetExternal(), GetStart(), GetEnd()); return ret; } }