public Exp testlist_comp(bool tuple)
{
Exp e;
Token token;
if (Peek(TokenType.RBRACKET, TokenType.RPAREN))
{
token = lexer.Peek();
var empty = new List<Exp>();
if (tuple)
return new PyTuple(empty, filename, token.Start, token.End);
else
return new PyList(empty, filename, token.Start, token.End);
}
if (Peek(TokenType.OP_STAR))
e = star_expr();
else
e = test();
if (Peek(TokenType.COMMENT))
e.Comment = (string)Expect(TokenType.COMMENT).Value;
Exp e2;
if (Peek(TokenType.For))
{
e2 = comp_for();
return new ListComprehension(e, e2, filename, e.Start, e2.End);
}
else
{
bool forceTuple = false;
var exprs = new List<Exp> { e };
while (PeekAndDiscard(TokenType.COMMA))
{
while (PeekAndDiscard(TokenType.COMMENT))
;
// Trailing comma forces a tuple.
if (Peek(TokenType.RBRACKET, TokenType.RPAREN))
{
forceTuple = true;
break;
}
if (Peek(TokenType.OP_STAR))
e2 = star_expr();
else
exprs.Add(test());
if (Peek(TokenType.COMMENT))
e.Comment = (string)Expect(TokenType.COMMENT).Value;
}
if (tuple)
{
if (exprs.Count == 1 && !forceTuple)
{
return exprs[0];
}
else
{
return new PyTuple(exprs, filename, exprs[0].Start, exprs.Last().End);
}
}
else
{
return new PyList(exprs, filename, exprs[0].Start, exprs.Last().End);
}
}
}