p.closeScope()
        assert(p.topScope == nil, "unbalanced scopes")
 
+       // If a semicolon was inserted, consume it;
+       // report an error if there's more tokens.
+       if p.tok == token.SEMICOLON {
+               p.next()
+       }
+       p.expect(token.EOF)
+
        if p.errors.Len() > 0 {
                p.errors.Sort()
                return nil, p.errors.Err()
 
        }
        // sanity check
        if _, ok := x.(*ast.BinaryExpr); !ok {
-               t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x)
+               t.Errorf("ParseExpr(%s): got %T, want *ast.BinaryExpr", src, x)
        }
 
        // a valid type expression
        }
        // sanity check
        if _, ok := x.(*ast.StructType); !ok {
-               t.Errorf("ParseExpr(%s): got %T, expected *ast.StructType", src, x)
+               t.Errorf("ParseExpr(%s): got %T, want *ast.StructType", src, x)
        }
 
        // an invalid expression
        src = "a + *"
        _, err = ParseExpr(src)
        if err == nil {
-               t.Fatalf("ParseExpr(%s): %v", src, err)
+               t.Fatalf("ParseExpr(%s): got no error", src)
+       }
+
+       // a valid expression followed by extra tokens is invalid
+       src = "a[i] := x"
+       _, err = ParseExpr(src)
+       if err == nil {
+               t.Fatalf("ParseExpr(%s): got no error", src)
        }
 
-       // it must not crash
+       // ParseExpr must not crash
        for _, src := range valids {
                ParseExpr(src)
        }