mirror of
https://github.com/golang/go
synced 2024-11-13 17:30:24 -07:00
- support for range clauses
R=r OCL=21030 CL=21030
This commit is contained in:
parent
a3155bdb09
commit
c9859e7bc6
@ -971,12 +971,25 @@ func (P *Parser) ParseExpression(prec int) *AST.Expr {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Statements
|
||||
|
||||
func (P *Parser) ParseSimpleStat() *AST.Stat {
|
||||
func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
|
||||
P.Trace("SimpleStat");
|
||||
|
||||
s := AST.BadStat;
|
||||
x := P.ParseExpressionList();
|
||||
|
||||
is_range := false;
|
||||
if range_ok && P.tok == Scanner.COLON {
|
||||
pos := P.pos;
|
||||
P.Next();
|
||||
y := P.ParseExpression(1);
|
||||
if x.Len() == 1 {
|
||||
x = P.NewExpr(pos, Scanner.COLON, x, y);
|
||||
is_range = true;
|
||||
} else {
|
||||
P.Error(pos, "expected initialization, found ':'");
|
||||
}
|
||||
}
|
||||
|
||||
switch P.tok {
|
||||
case Scanner.COLON:
|
||||
// label declaration
|
||||
@ -993,16 +1006,38 @@ func (P *Parser) ParseSimpleStat() *AST.Stat {
|
||||
Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN,
|
||||
Scanner.REM_ASSIGN, Scanner.AND_ASSIGN, Scanner.OR_ASSIGN,
|
||||
Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN:
|
||||
// assignment
|
||||
// declaration/assignment
|
||||
pos, tok := P.pos, P.tok;
|
||||
P.Next();
|
||||
y := P.ParseExpressionList();
|
||||
y := AST.BadExpr;
|
||||
if P.tok == Scanner.RANGE {
|
||||
range_pos := P.pos;
|
||||
P.Next();
|
||||
y = P.ParseExpression(1);
|
||||
y = P.NewExpr(range_pos, Scanner.RANGE, nil, y);
|
||||
if tok != Scanner.DEFINE && tok != Scanner.ASSIGN {
|
||||
P.Error(pos, "expected '=' or ':=', found '" + Scanner.TokenString(tok) + "'");
|
||||
}
|
||||
} else {
|
||||
y = P.ParseExpressionList();
|
||||
if is_range {
|
||||
P.Error(y.pos, "expected 'range', found expression");
|
||||
}
|
||||
if xl, yl := x.Len(), y.Len(); xl > 1 && yl > 1 && xl != yl {
|
||||
P.Error(x.pos, "arity of lhs doesn't match rhs");
|
||||
}
|
||||
}
|
||||
s = AST.NewStat(x.pos, Scanner.EXPRSTAT);
|
||||
s.expr = AST.NewExpr(pos, tok, x, y);
|
||||
|
||||
case Scanner.RANGE:
|
||||
pos := P.pos;
|
||||
P.Next();
|
||||
y := P.ParseExpression(1);
|
||||
y = P.NewExpr(pos, Scanner.RANGE, nil, y);
|
||||
s = AST.NewStat(x.pos, Scanner.EXPRSTAT);
|
||||
s.expr = AST.NewExpr(pos, Scanner.DEFINE, x, y);
|
||||
|
||||
default:
|
||||
var pos, tok int;
|
||||
if P.tok == Scanner.INC || P.tok == Scanner.DEC {
|
||||
@ -1072,7 +1107,8 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
|
||||
prev_lev := P.expr_lev;
|
||||
P.expr_lev = -1;
|
||||
if P.tok != Scanner.SEMICOLON {
|
||||
s.init = P.ParseSimpleStat();
|
||||
s.init = P.ParseSimpleStat(keyword == Scanner.FOR);
|
||||
// TODO check for range clause and exit if found
|
||||
}
|
||||
if P.tok == Scanner.SEMICOLON {
|
||||
P.Next();
|
||||
@ -1082,7 +1118,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
|
||||
if keyword == Scanner.FOR {
|
||||
P.Expect(Scanner.SEMICOLON);
|
||||
if P.tok != Scanner.LBRACE {
|
||||
s.post = P.ParseSimpleStat();
|
||||
s.post = P.ParseSimpleStat(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1284,7 +1320,7 @@ func (P *Parser) ParseStatement() *AST.Stat {
|
||||
Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand
|
||||
Scanner.LBRACK, Scanner.STRUCT, // composite type
|
||||
Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary
|
||||
s = P.ParseSimpleStat();
|
||||
s = P.ParseSimpleStat(false);
|
||||
case Scanner.GO:
|
||||
s = P.ParseGoStat();
|
||||
case Scanner.RETURN:
|
||||
|
@ -582,6 +582,9 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) {
|
||||
if x.x == nil {
|
||||
// unary expression
|
||||
P.Token(x.pos, x.tok);
|
||||
if x.tok == Scanner.RANGE {
|
||||
P.separator = blank;
|
||||
}
|
||||
} else {
|
||||
// binary expression
|
||||
P.Expr1(x.x, prec);
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
|
||||
const /* enum */ (
|
||||
const /* enum1 */ (
|
||||
EnumTag0 = iota;
|
||||
EnumTag1;
|
||||
EnumTag2;
|
||||
@ -25,6 +25,13 @@ const /* enum */ (
|
||||
)
|
||||
|
||||
|
||||
const /* enum2 */ (
|
||||
a, b = iota*2 + 1, iota*2;
|
||||
c, d;
|
||||
e, f;
|
||||
)
|
||||
|
||||
|
||||
type S struct {}
|
||||
|
||||
|
||||
@ -37,7 +44,7 @@ type T struct {
|
||||
|
||||
var (
|
||||
A = 5;
|
||||
a, b, c int = 0, 0, 0;
|
||||
u, v, w int = 0, 0, 0;
|
||||
foo = "foo";
|
||||
)
|
||||
|
||||
@ -66,6 +73,41 @@ func f2(tag int) {
|
||||
}
|
||||
|
||||
|
||||
func f3(a *[]int, m *map[string] int) {
|
||||
println("A1");
|
||||
for i := range a {
|
||||
println(i);
|
||||
}
|
||||
|
||||
println("A2");
|
||||
for i, x := range a {
|
||||
println(i, x);
|
||||
}
|
||||
|
||||
println("A3");
|
||||
for i : x := range a {
|
||||
println(i, x);
|
||||
}
|
||||
|
||||
println("M1");
|
||||
for i range m {
|
||||
println(i);
|
||||
}
|
||||
|
||||
println("M2");
|
||||
for i, x range m {
|
||||
println(i, x);
|
||||
}
|
||||
|
||||
println("M3");
|
||||
var i string;
|
||||
var x int;
|
||||
for i : x = range m {
|
||||
println(i, x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
// the prologue
|
||||
for i := 0; i <= 10 /* limit */; i++ {
|
||||
@ -74,6 +116,7 @@ func main() {
|
||||
println(i + 1000); // the index + 1000
|
||||
println();
|
||||
}
|
||||
f3(&[]int{2, 3, 5, 7}, map[string]int{"two":2, "three":3, "five":5, "seven":7});
|
||||
// the epilogue
|
||||
println("foo"); // foo
|
||||
println("foobar"); // foobar
|
||||
|
Loading…
Reference in New Issue
Block a user